package ru.yandex.qe.dispenser.application.startup;

import java.util.Arrays;

import org.jetbrains.annotations.NotNull;
import org.springframework.dao.DuplicateKeyException;

import ru.yandex.qe.dispenser.api.v1.DiQuotingMode;
import ru.yandex.qe.dispenser.api.v1.DiResourceType;
import ru.yandex.qe.dispenser.api.v1.DiYandexGroupType;
import ru.yandex.qe.dispenser.domain.EntitySpec;
import ru.yandex.qe.dispenser.domain.Person;
import ru.yandex.qe.dispenser.domain.PersonAffiliation;
import ru.yandex.qe.dispenser.domain.Project;
import ru.yandex.qe.dispenser.domain.QuotaSpec;
import ru.yandex.qe.dispenser.domain.Resource;
import ru.yandex.qe.dispenser.domain.Service;
import ru.yandex.qe.dispenser.domain.YaGroup;
import ru.yandex.qe.dispenser.domain.hierarchy.Role;

public class DevelopmentInitialState extends InitialState {
    @Override
    public void configure() throws DuplicateKeyException {
        final Person whistler = personDao.create(new Person("whistler", 1120000000022037L, false, false, false, PersonAffiliation.YANDEX));
        final Person amosovF = personDao.create(new Person("amosov-f", 1120000000022901L, false, false, false, PersonAffiliation.YANDEX));
        final Person zombMobsearch = personDao.create(new Person("zomb-mobsearch", 1120000000017942L, true, false, false, PersonAffiliation.EXTERNAL));
        final Person starlight = personDao.create(new Person("starlight", 1120000000008384L, false, false, false, PersonAffiliation.YANDEX));
        final Person vkokarev = personDao.create(new Person("vkokarev", 1120000000019824L, false, false, false, PersonAffiliation.YANDEX));
        final Person alexkoshelev = personDao.create(new Person("alexkoshelev", 1120000000000406L, false, false, false, PersonAffiliation.YANDEX));
        final Person glader = personDao.create(new Person("glader", 1120000000000390L, false, true, false, PersonAffiliation.YANDEX));
        final Person zanar = personDao.create(new Person("zanar", 1120000000048123L, false, true, false, PersonAffiliation.YANDEX));
        final Person spacy = personDao.create(new Person("spacy", 1120000000010590L, false, false, false, PersonAffiliation.YANDEX));
        final Person denblo = personDao.create(new Person("denblo", 1120000000107974L, false, false, false, PersonAffiliation.YANDEX));
        dispenserAdminsDao.setDispenserAdmins(Arrays.asList(amosovF, vkokarev, starlight, alexkoshelev, glader, zanar, spacy, denblo));
        final Person cmind = personDao.create(new Person("cmind", 1120000000016620L, false, false, false, PersonAffiliation.YANDEX));
        final Person samid = personDao.create(new Person("samid", 1120000000025003L, false, false, false, PersonAffiliation.YANDEX));;
        final Person lanium = personDao.create(new Person("lanium", 1120000000022451L, false, false, false, PersonAffiliation.YANDEX));;
        final Person mesherin = personDao.create(new Person("mesherin", 1120000000005929L, false, false, false, PersonAffiliation.YANDEX));
        final Person sukhoi = personDao.create(new Person("sukhoi", 1120000000004942L, false, false, false, PersonAffiliation.YANDEX));
        final Person mklimushkin = personDao.create(new Person("mklimushkin", 1120000000010071L, false, false, false, PersonAffiliation.YANDEX));
        final Person algorc = personDao.create(new Person("algorc", 1120000000014342L, false, true, false, PersonAffiliation.YANDEX));
        final Person mincer = personDao.create(new Person("mincer", 1120000000014063L, false, false, false, PersonAffiliation.YANDEX));
        final Person timofeich = personDao.create(new Person("timofeich", 1120000000023903L, false, false, false, PersonAffiliation.YANDEX));
        final Person epar = personDao.create(new Person("epar", 1120000000008525L, false, false, false, PersonAffiliation.YANDEX));
        final Person vnik = personDao.create(new Person("vnik", 1120000000000762L, false, true, false, PersonAffiliation.YANDEX));
        final Person orepin = personDao.create(new Person("orepin", 1120000000011792L, false, false, false, PersonAffiliation.YANDEX));
        final Person skyhawk = personDao.create(new Person("skyhawk", 1120000000012671L, false, true, false, PersonAffiliation.YANDEX));
        final Person akaluzhin = personDao.create(new Person("akaluzhin", 1120000000017045L, false, false, false, PersonAffiliation.YANDEX));
        final Person realcater = personDao.create(new Person("realcater", 1120000000008963L, false, true, false, PersonAffiliation.YANDEX));
        final Person melton = personDao.create(new Person("melton", 1120000000000880L, false, false, false, PersonAffiliation.YANDEX));
        final Person nkmakarov = personDao.create(new Person("nkmakarov", 1120000000007595L, false, false, false, PersonAffiliation.YANDEX));
        final Person ustas = personDao.create(new Person("ustas", 1120000000000657L, false, false, false, PersonAffiliation.YANDEX));
        final Person zador = personDao.create(new Person("zador", 1120000000000876L, false, false, false, PersonAffiliation.YANDEX));
        final Person panoff = personDao.create(new Person("panoff", 1120000000001572L, false, true, false, PersonAffiliation.YANDEX));
        final Person shmakova = personDao.create(new Person("shmakova", 1120000000017137L, false, false, false, PersonAffiliation.YANDEX));
        final Person vsavenkov = personDao.create(new Person("vsavenkov", 1120000000000878L, false, false, false, PersonAffiliation.YANDEX));
        final Person trofimenkov = personDao.create(new Person("trofimenkov", 1120000000007925L, false, false, false, PersonAffiliation.YANDEX));
        final Person alex_sh = personDao.create(new Person("alex-sh", 1120000000004890L, false, false, false, PersonAffiliation.YANDEX));
        personDao.create(new Person("sancho", 1120000000006106L, false, false, false, PersonAffiliation.YANDEX));
        personDao.create(new Person("qdeee", 1120000000015512L, false, false, false, PersonAffiliation.YANDEX));
        personDao.create(new Person("robot-nirvana", 1120000000036908L, true, false, false, PersonAffiliation.EXTERNAL));
        personDao.create(new Person("robot-dispenser", 1120000000128362L, true, false, false, PersonAffiliation.EXTERNAL));
        personDao.create(new Person("robot-verter", 1120000000022364L, true, false, false, PersonAffiliation.EXTERNAL));
        personDao.create(new Person("robot-scraper", 1120000000035603L, true, false, false, PersonAffiliation.EXTERNAL));
        personDao.create(new Person("yushkovsky", 1120000000040368L, false, false, false, PersonAffiliation.YANDEX));

        final YaGroup yandexDepartment = groupDao.createIfAbsent(new YaGroup("yandex", DiYandexGroupType.DEPARTMENT, 962L, false));
        final YaGroup virtualRobots = groupDao.createIfAbsent(new YaGroup("virtual_robots", DiYandexGroupType.DEPARTMENT, 24700L, false));
        final YaGroup virtual = groupDao.createIfAbsent(new YaGroup("virtual", DiYandexGroupType.DEPARTMENT, 8174L, false));
        final YaGroup ext = groupDao.createIfAbsent(new YaGroup("ext", DiYandexGroupType.DEPARTMENT, 5L, false));

        final Project yandex = projectDao.createIfAbsent(new Project("yandex", "Яндекс", null));
        final Project defolt = projectDao.createIfAbsent(new Project("default", "default", yandex));
        final Project pogoda = projectDao.create(new Project("pogoda", "Погода", yandex));
        final Project geosearch = projectDao.create(new Project("geosearch", "Геопоиск", yandex));
        final Project conveier = projectDao.create(new Project("konveier", "Конвейер", yandex));
        final Project web = projectDao.create(new Project("web", "Web", conveier));
        final Project video = projectDao.create(new Project("video", "Video", conveier));
        final Project images = projectDao.create(new Project("images", "Images", conveier));
        final Project blender = projectDao.create(new Project("blender", "Blender", conveier));
        final Project cvlab = projectDao.create(new Project("cvlab", "Компьютерное зрение", yandex));
        final Project videofresh = projectDao.create(new Project("videofresh", "Свежесть Видео", yandex));
        final Project socialfresh = projectDao.create(new Project("socialfresh", "Свеже-социальный поиск", yandex));
        final Project freshness = projectDao.create(new Project("freshness", "Свежесть", socialfresh));
        final Project sport = projectDao.create(new Project("sport", "Спорт", socialfresh));
        final Project push = projectDao.create(new Project("push", "Пуши", socialfresh));
        final Project ppl = projectDao.create(new Project("ppl", "ППЛ", socialfresh));
        final Project suggest = projectDao.create(new Project("suggest", "Саджест", socialfresh));
        final Project rem = projectDao.create(new Project("rem", "REM", socialfresh));
        final Project keyboard = projectDao.create(new Project("keyboard", "Клавиатура", socialfresh));
        final Project newsWizard = projectDao.create(new Project("newswizard", "Колдунщик новостей", socialfresh));
        projectDao.create(new Project("dispenser", "Dispenser", yandex));

        initForNirvana(yandex, zombMobsearch);
        initForClusterApi(yandex, yandexDepartment, zombMobsearch);
        initForScraper(yandex, zombMobsearch);

        projectDao.attach(whistler, yandex, Role.RESPONSIBLE);
        projectDao.attach(zombMobsearch, yandex, Role.MEMBER);
        projectDao.attach(yandexDepartment, defolt, Role.MEMBER);
        projectDao.attach(virtualRobots, defolt, Role.MEMBER);
        projectDao.attach(virtual, defolt, Role.MEMBER);
        projectDao.attach(ext, defolt, Role.MEMBER);

        projectDao.attach(cmind, pogoda, Role.RESPONSIBLE);
        projectDao.attach(sukhoi, geosearch, Role.RESPONSIBLE);
        projectDao.attach(mklimushkin, web, Role.RESPONSIBLE);
        projectDao.attach(algorc, web, Role.RESPONSIBLE);
        projectDao.attach(mincer, video, Role.RESPONSIBLE);
        projectDao.attach(timofeich, images, Role.RESPONSIBLE);
        projectDao.attach(vnik, blender, Role.RESPONSIBLE);
        projectDao.attach(skyhawk, cvlab, Role.RESPONSIBLE);
        projectDao.attach(akaluzhin, videofresh, Role.RESPONSIBLE);
        projectDao.attach(alex_sh, socialfresh, Role.RESPONSIBLE);

        projectDao.attach(cmind, pogoda, Role.MEMBER);
        projectDao.attach(samid, pogoda, Role.MEMBER);
        projectDao.attach(lanium, pogoda, Role.MEMBER);
        projectDao.attach(mesherin, geosearch, Role.MEMBER);
        projectDao.attach(epar, blender, Role.MEMBER);
        projectDao.attach(vnik, blender, Role.MEMBER);
        projectDao.attach(orepin, blender, Role.MEMBER);

        projectDao.attach(realcater, freshness, Role.MEMBER);
        projectDao.attach(melton, freshness, Role.MEMBER);
        projectDao.attach(nkmakarov, freshness, Role.MEMBER);
        projectDao.attach(realcater, sport, Role.MEMBER);
        projectDao.attach(ustas, sport, Role.MEMBER);
        projectDao.attach(zador, push, Role.MEMBER);
        projectDao.attach(realcater, push, Role.MEMBER);
        projectDao.attach(ustas, push, Role.MEMBER);
        projectDao.attach(nkmakarov, ppl, Role.MEMBER);
        projectDao.attach(panoff, ppl, Role.MEMBER);
        projectDao.attach(shmakova, suggest, Role.MEMBER);
        projectDao.attach(vsavenkov, suggest, Role.MEMBER);
        projectDao.attach(trofimenkov, rem, Role.MEMBER);
        projectDao.attach(panoff, rem, Role.MEMBER);
        projectDao.attach(shmakova, keyboard, Role.MEMBER);
        projectDao.attach(nkmakarov, newsWizard, Role.MEMBER);
        projectDao.attach(melton, newsWizard, Role.MEMBER);
        projectDao.attach(shmakova, newsWizard, Role.MEMBER);
    }

    private void initForNirvana(@NotNull final Project yandex, @NotNull final Person zombMobsearch) {
        final Service nirvana = serviceDao.create(Service.withKey("nirvana").withName("Нирвана").withAbcServiceId(961).build());
        final Resource diskSpace = resourceDao.create(new Resource.Builder("yt-disk", nirvana)
                .name("Диск в YT")
                .description("Размер на диске в YT")
                .type(DiResourceType.STORAGE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource chunkCount = resourceDao.create(new Resource.Builder("yt-chunk", nirvana)
                .name("Чанки в YT")
                .description("Число занимаемых чанков в YT")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource nodeCount = resourceDao.create(new Resource.Builder("yt-node", nirvana)
                .name("Ноды в YT")
                .description("Число занимаемых нодов в YT")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final QuotaSpec diskSpaceQuota = quotaSpecDao.create(new QuotaSpec.Builder("yt-disk-quota", diskSpace)
                .description("Квота на Диск в YT")
                .build());
        final QuotaSpec chunkCountQuota = quotaSpecDao.create(new QuotaSpec.Builder("yt-chunk-quota", chunkCount)
                .description("Квота на Чанки в YT")
                .build());
        final QuotaSpec nodeCountQuota = quotaSpecDao.create(new QuotaSpec.Builder("yt-node-quota", nodeCount)
                .description("Квота на Ноды в YT")
                .build());
        final EntitySpec nirvanaYtFile = EntitySpec.builder()
                .withKey("yt-file")
                .withDescription("Файлы в YT")
                .overResource(diskSpace)
                .overResource(chunkCount)
                .overResource(nodeCount)
                .build();
        entitySpecDao.create(nirvanaYtFile);

        final Resource workflowCreate = resourceDao.create(new Resource.Builder("workflow-create", nirvana)
                .name("Создано графов")
                .description("Количество созданных графов")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource workflowStart = resourceDao.create(new Resource.Builder("workflow-start", nirvana)
                .name("Запущено графов")
                .description("Количество запущенных графов")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource workflowBlockStart = resourceDao.create(new Resource.Builder("workflow-block-start", nirvana)
                .name("Запущено блоков")
                .description("Количество запущенных блоков графов")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());

        quotaSpecDao.create(new QuotaSpec.Builder("workflow-create-quota", workflowCreate)
                .description("Квота на количество созданных графов")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("workflow-start-quota", workflowStart)
                .description("Квота на количество запущенных графов")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("workflow-block-start-quota", workflowBlockStart)
                .description("Квота на количество запущенных блоков графов")
                .build());

        final EntitySpec createWorkflow = EntitySpec.builder()
                .withKey("nirvana-workflow-create")
                .withDescription("Создание графа в Нирване")
                .overResource(workflowCreate)
                .build();
        entitySpecDao.create(createWorkflow);
        final EntitySpec startWorkflow = EntitySpec.builder()
                .withKey("nirvana-workflow-start")
                .withDescription("Запуск графа в Нирване")
                .overResource(workflowStart)
                .overResource(workflowBlockStart)
                .build();
        entitySpecDao.create(startWorkflow);

        final Person sancho = personDao.readPersonByLogin("sancho");
        final Person qdeee = personDao.readPersonByLogin("qdeee");
        final Person robotNirvana = personDao.readPersonByLogin("robot-nirvana");
        serviceDao.attachAdmins(nirvana, Arrays.asList(sancho, qdeee));
        serviceDao.attachTrustees(nirvana, Arrays.asList(robotNirvana, zombMobsearch));
        projectDao.attach(qdeee, yandex, Role.RESPONSIBLE);
        projectDao.attach(qdeee, yandex, Role.MEMBER);
    }

    protected void initForClusterApi(@NotNull final Project yandex, @NotNull final YaGroup yandexDepartment, @NotNull final Person zombMobsearch) {
        final Service clusterApi = serviceDao.create(Service.withKey("cluster-api").withName("Cluster API").withAbcServiceId(1783).build());
        final Resource crhn = resourceDao.create(new Resource.Builder("crhn", clusterApi)
                .name("Валюта CRHN")
                .description("Комплексный ресурс CRHN в попугаях")
                .type(DiResourceType.MONEY)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource cpu = resourceDao.create(new Resource.Builder("cpu", clusterApi)
                .name("CPU")
                .description("Вычислительные ресурсы")
                .type(DiResourceType.POWER)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource ram = resourceDao.create(new Resource.Builder("ram", clusterApi)
                .name("RAM")
                .description("Оперативная память")
                .type(DiResourceType.MEMORY)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource hdd = resourceDao.create(new Resource.Builder("hdd", clusterApi)
                .name("HDD")
                .description("Дисковая память")
                .type(DiResourceType.MEMORY)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource net = resourceDao.create(new Resource.Builder("net", clusterApi)
                .name("Сеть")
                .description("Пропускная способность сети")
                .type(DiResourceType.TRAFFIC)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("crhn-quota", crhn)
                .description("Квота на CRHN")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("cpu-quota", cpu)
                .description("Квота на CPU")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("ram-quota", ram)
                .description("Квота на RAM")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("hdd-quota", hdd)
                .description("Квота на HDD")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("net-quota", net)
                .description("Квота на Сеть")
                .build());
        final EntitySpec workload = EntitySpec.builder()
                .withKey("workload").withDescription("Workload")
                .overResource(crhn)
                .overResource(cpu)
                .overResource(ram)
                .overResource(hdd)
                .overResource(net)
                .build();
        entitySpecDao.create(workload);

        final Project nirvanaProject = projectDao.create(Project.withKey("nirvana").name("Нирвана в Cluster API").description("Только этот проект Нирвана пока что прокидывает в Cluster API").parent(yandex).build());
        projectDao.attach(yandexDepartment, nirvanaProject, Role.MEMBER);

        final Person yushkovsky = personDao.readPersonByLogin("yushkovsky");
        final Person robotVerter = personDao.readPersonByLogin("robot-verter");
        projectDao.attach(yushkovsky, yandex, Role.RESPONSIBLE);
        projectDao.attach(yushkovsky, yandex, Role.MEMBER);
        serviceDao.attachAdmin(clusterApi, yushkovsky);
        serviceDao.attachTrustees(clusterApi, Arrays.asList(robotVerter, zombMobsearch));
    }

    protected void initForScraper(@NotNull final Project yandex, @NotNull final Person zombMobsearch) {
        final Service scraper = serviceDao.create(Service.withKey("scraper").withName("Scraper").withAbcServiceId(1534).build());
        final Resource batchCount = resourceDao.create(new Resource.Builder("created-batches", scraper)
                .name("Созданные батчи")
                .description("Количество созданных батчей")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource yandexRequests = resourceDao.create(new Resource.Builder("yandex-requests", scraper)
                .name("Запросы к Яндексу")
                .description("Количество запросов к Яндексу")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource googleRequests = resourceDao.create(new Resource.Builder("google-requests", scraper)
                .name("Запросы к Гуглу")
                .description("Количество запросов к Гуглу")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        final Resource otherRequests = resourceDao.create(new Resource.Builder("other-requests", scraper)
                .name("Другие запросы")
                .description("Количество запросов не к Яндексу и не к Гуглу")
                .type(DiResourceType.ENUMERABLE)
                .mode(DiQuotingMode.ENTITIES_ONLY)
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("created-batches-quota", batchCount)
                .description("Квота на созданные батчи")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("yandex-requests-quota", yandexRequests)
                .description("Квота на Яндексовые запросы")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("google-requests-quota", googleRequests)
                .description("Квота на Гугловые запросы")
                .build());
        quotaSpecDao.create(new QuotaSpec.Builder("other-requests-quota", otherRequests)
                .description("Квота на запросы не к Яндексу и не к Гуглу")
                .build());
        final EntitySpec scraperBatch = EntitySpec.builder()
                .withKey("scraper-batch")
                .withDescription("Батч в Scraper")
                .overResource(batchCount)
                .overResource(yandexRequests)
                .overResource(googleRequests)
                .overResource(otherRequests)
                .build();
        entitySpecDao.create(scraperBatch);

        final Person amosov = personDao.readPersonByLogin("amosov-f");
        final Person robotScraper = personDao.readPersonByLogin("robot-scraper");
        projectDao.attach(amosov, yandex, Role.RESPONSIBLE);
        projectDao.attach(amosov, yandex, Role.MEMBER);
        serviceDao.attachAdmin(scraper, amosov);
        serviceDao.attachTrustees(scraper, Arrays.asList(robotScraper, zombMobsearch));
    }
}
