package com.alterdekim.game.component;

import com.alterdekim.flash.decompiler.FlashDecompiler;
import com.alterdekim.flash.decompiler.ShockwaveFile;
import com.alterdekim.flash.decompiler.compiler.FlashCompiler;
import com.alterdekim.flash.decompiler.mapper.FlashMapper;
import com.alterdekim.flash.decompiler.mapper.OutputObject;
import com.alterdekim.flash.decompiler.tag.DoAction;
import com.alterdekim.flash.decompiler.tag.TagType;
import com.alterdekim.flash.decompiler.translator.Flash2Java;
import com.alterdekim.flash.decompiler.translator.Java2Flash;
import com.alterdekim.game.component.game.avatar.BodyPartType;
import com.alterdekim.game.config.ServerConfig;
import com.alterdekim.game.entity.*;
import com.alterdekim.game.service.*;
import com.alterdekim.game.storage.StorageProperties;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.javatuples.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;

@Slf4j
@Component
public class StartUpListener {

    private static final String ADMIN_USERNAME = "admin";

    @Getter
    private long startTime;

    @Autowired
    private ServerConfig config;

    @Autowired
    private StorageProperties storageProperties;

    @Autowired
    private UserService userService;

    @Autowired
    private MRTService mrtService;

    @Autowired
    private MRService mrService;

    @Autowired
    private TRService trService;

    @Autowired
    private ROService roService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private GoodTagService goodTagService;

    @Autowired
    private CatalogService catalogService;

    @Autowired
    private GoodMagicService goodMagicService;

    @Autowired
    private GoodSmileService goodSmileService;

    @Autowired
    private GCDService gcdService;

    @Autowired
    private MAService maService;

    @Autowired
    private AchievementService achievementService;

    @Autowired
    private BackgroundService backgroundService;

    @Autowired
    private LibraryService libraryService;

    @Autowired
    private SportInventoryService sportInventoryService;

    @Autowired
    private VisaService visaService;

    @Autowired
    private MissionService missionService;

    @Autowired
    private GAAccountService gaAccountService;

    @Autowired
    private PriceExchangeService priceExchangeService;

    @Autowired
    private PriceLicenseService priceLicenseService;

    @Autowired
    private PhoneIconService phoneIconService;

    @Autowired
    private GameIconService gameIconService;

    @Autowired
    private IncompatibleService incompatibleService;

    @Autowired
    private LevelExperienceService levelExperienceService;

    @Autowired
    private SmileService smileService;

    @Autowired
    private AvatarInventoryService avatarInventoryService;

    @Autowired
    private LocationService locationService;

    @Autowired
    private PreloaderService preloaderService;

    @Autowired
    private PromotionService promotionService;

    @Autowired
    private PromotionBannerService promotionBannerService;

    @Autowired
    private MiniGameService miniGameService;

    @EventListener
    public void onApplicationEvent(ContextRefreshedEvent event) {
        this.startTime = System.currentTimeMillis();

        if( userService.findByUsername(ADMIN_USERNAME) != null ) {

            // todo: remove hardcoded cache folder
            new File("cache/").mkdirs();

            Map<String, Object> root = new HashMap<>();
            Map<String, Object> mr = new HashMap<>();
            mr.put("MR", FlashMapper.objToMap(mrService.getAll()));
            mr.put("RO", FlashMapper.objToMap(roService.getAll()));
            mr.put("TR", FlashMapper.objToMap(trService.getAll()));
            mr.put("MRT", FlashMapper.simpleToMap(mrtService.getAll()));
            root.put("resources", mr);

            try { // todo: and here too ( abolish hardcoded paths )
                Files.write(Path.of("cache/resources.swf"), new FlashCompiler(new Java2Flash().convert(root)).compile(), StandardOpenOption.CREATE);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        if( userService.findByUsername(ADMIN_USERNAME) != null ) return;
        String pwd = UUID.randomUUID().toString();
        log.info("Your admin account password is: {}\nChange it later.", pwd);
        userService.saveUser(ADMIN_USERNAME, pwd, Role.RoleType.RoleAdmin);

        log.info("Moving pre-compiled data to our database.");
        try {
            processResources(storageProperties.getLocation() + File.separator + config.getDefaultResourcesPath());
            processBase(storageProperties.getLocation() + File.separator + config.getDefaultBasePath());
            processCatalogs(storageProperties.getLocation() + File.separator + config.getDefaultCatalogsPath());
        } catch (IOException e) {
            log.error("Unable to move pre-compiled data to the server's database: {}", e.getMessage());
        }
        log.info("Pushing default data blobs to the database");
        pushPreloaders();
        pushPromotions();
        pushPromotionBanners();

        pushBodyParts();
        pushLocations();
        pushLocationObjects();

        pushMiniGames();

        pushHouseLocations();

        pushPhoneSkins();
        log.info("Initialization complete");
    }

    private void pushMiniGames() {
        miniGameService.save(new MiniGame(0L, "Рентген", 0, 0, 4250, 1d, 2, true, true, false, 0L, 0L, "1", ""));
        miniGameService.save(new MiniGame(1L, "Дары леса", 10120, 1291, 1749, 10d, 1, true, false, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(2L, "Катер", 10089, 516, 4265, 100d, 1, true, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(3L, "Волейбол", 10087, 513, 301, 100d, 1, true, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(4L, "Кафе", 10088, 515, 310, 1d, 0, true, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(5L, "Труба", 10084, 1104, 11763, 1d, 0, false, true, true, 0L, 0L, "1", ""));
        miniGameService.save(new MiniGame(6L, "Секретики", 10097, 806, 763, 1d, 0, true, false, true, 1000L, 10000L, "1", ""));
        miniGameService.save(new MiniGame(7L, "Смешарики", 10086, 510, 3126, 1d, 1, true, true, true, 1000L, 10000L, "0", ""));
        miniGameService.save(new MiniGame(8L, "Модельер", 10101, 948, 4300, 5d, 0, false, false, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(9L, "Горки", 10095, 557, 341, 40d, 1, true, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(10L, "Скачки", 10093, 518, 319, 1d, 0, true, true, true, 1000L, 10000L, "0", ""));
        miniGameService.save(new MiniGame(11L, "Футбол", 10112, 1212, 4247, 1d, 3, true, true, true, 1000L, 30000L, "0", ""));
        miniGameService.save(new MiniGame(12L, "Няня", 10083, 505, 4241, 30d, 0, false, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(13L, "Двигатель", 10094, 519, 322, 5d, 0, false, true, true, 0L, 0L, "0", ""));
        miniGameService.save(new MiniGame(14L, "Шарабудка", 8054, 3218, 1127, 1d, 0, false, true, true, 0L, 0L, "1", ""));
        miniGameService.save(new MiniGame(92L, "Трасса", 0, 0, 4267, 1d, 1, false, false, true, 0L, 0L, "1", ""));
        miniGameService.save(new MiniGame(206L, "Муравей", 2148, 2148, 3170, 1d, 0, true, false, true, 0L, 0L, "1", ""));
    }

    private void pushPhoneSkins() {
        phoneIconService.findAll()
                        .stream()
                        .map(i -> Pair.with(i.getId(), mrService.findById(i.getIconMRId().longValue())))
                        .filter(i -> i.getValue1().isPresent())
                        .map(i -> Pair.with(i.getValue0(), i.getValue1().get()))
                        .filter(i -> this.mrService.findByUrl(i.getValue1().getUrl().replace("-icon.swf", "-skin.swf"), 26).isPresent())
                        .forEach(i ->
                            this.phoneIconService.save(
                                    new PhoneSkin(
                                            i.getValue0(),
                                            this.mrService.findByUrl(i.getValue1().getUrl().replace("-icon.swf", "-skin.swf"), 26).get().getId()
                                    )
                            )
                        );
    }

    private void pushPromotionBanners() {
        promotionBannerService.savePromotionBanner(new PromotionBanner(9841, true));
        promotionBannerService.savePromotionBanner(new PromotionBanner(9955, true));
        promotionBannerService.savePromotionBanner(new PromotionBanner(12512, true));
    }

    private void pushPromotions() {
        promotionService.savePromotion(new Promotion(5778, "1", true));
        promotionService.savePromotion(new Promotion(5891, "1", true));
        promotionService.savePromotion(new Promotion(9818, "1", true));
    }

    private void pushPreloaders() {
        preloaderService.savePreloader(new Preloader(6857, 2000, true));
        preloaderService.savePreloader(new Preloader(11774, 2000, true));
        preloaderService.savePreloader(new Preloader(11994, 2000, true));
    }

    private void pushLocationObjects() {
        locationService.addObject(new LocationObjectInstance(2, 23, 0, 1045L, 9L, 445.0d, 50.0, "", "ТП на главную площадь (Смешмаг)"));
        locationService.addObject(new LocationObjectInstance(3, 7, 0, 1068L, 24L, 675.0d, 260.0, "", "Стол \"Смешарики\" (ППД)"));
        locationService.addObject(new LocationObjectInstance(3, 7, 0, 1069L, 24L, 670.0d, 330.0, "", "Стол \"Смешарики\" (ППД)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 4, 1243L, 24L, 24.0d, 72.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Зимняя лавка помидоров от копатыча (ППД)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 9, 4316L, 24L, 560.0d, 360.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила игры в \"Смешарики\" (ППД)"));
        locationService.addObject(new LocationObjectInstance(2, 32, 0, 1073L, 24L, 595.0d, 150.0, "", "ТП в Диско (ППД)"));
        locationService.addObject(new LocationObjectInstance(2, 45, 0, 7861L, 24L, 405.0d, 130.0, "", "ТП в Лес (ППД)"));
        locationService.addObject(new LocationObjectInstance(2, 53, 0, 7877L, 24L, 30.0d, 200.0, "", "ТП в Порт (ППД)"));
        locationService.addObject(new LocationObjectInstance(2, 22, 0, 228L, 24L, 160.0d, 130.0, "", "ТП в Парк (ППД)"));
        locationService.addObject(new LocationObjectInstance(2, 47, 0, 7849L, 23L, 620.0d, 215.0, "", "ТП на Площадь у Больнички (Главная площадь)"));
        locationService.addObject(new LocationObjectInstance(2, 53, 0, 7850L, 23L, 35.0d, 220.0, "", "ТП в Порт (Главная Площадь)"));
        locationService.addObject(new LocationObjectInstance(2, 10, 0, 1038L, 23L, 127.0d, 47.0, "", "ТП в Детский Сад (Главная Площадь)"));
        locationService.addObject(new LocationObjectInstance(2, 9, 0, 1039L, 23L, 358.0d, 37.0, "", "ТП в Смешмаг (Главная Площадь)"));
        locationService.addObject(new LocationObjectInstance(2, 40, 0, 1040L, 23L, 548.0d, 50.0, "", "ТП в Дом Мод (Главная Площадь)"));
        locationService.addObject(new LocationObjectInstance(2, 23, 0, 216L, 10L, 705.0d, 200.0, "", "ТП на Главную Площадь (Детский Сад)"));
        locationService.addObject(new LocationObjectInstance(2, 23, 0, 1054L, 40L, 20.0d, 175.0, "", "ТП на Главную Площадь (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(2, 38, 0, 7869L, 45L, 55.0d, 170.0, "", "ТП в Ромашковую Долину (Лес)"));
        locationService.addObject(new LocationObjectInstance(2, 24, 0, 7870L, 45L, 680.0d, 170.0, "", "ТП на ППД (Лес)"));
        locationService.addObject(new LocationObjectInstance(2, 24, 0, 286L, 32L, 123.0d, 70.0, "", "ТП на ПДД (Диско)"));
        locationService.addObject(new LocationObjectInstance(2, 47, 0, 7853L, 68L, 670.0d, 230.0, "", "ТП на Площадь у Больнички (Сити)"));
        locationService.addObject(new LocationObjectInstance(2, 71, 0, 2158L, 68L, 443.0d, 133.0, "", "ТП в Автосалон (Сити)"));
        locationService.addObject(new LocationObjectInstance(2, 0, 0, 3587L, 68L, 150.0d, 330.0, "", "ТП в Пещеру (Сити)"));
        locationService.addObject(new LocationObjectInstance(2, 67, 0, 1936L, 68L, 155.0d, 130.0, "", "ТП в Корпорацию Клубов (Сити)"));
        locationService.addObject(new LocationObjectInstance(2, 61, 0, 1946L, 68L, 645.0d, 170.0, "", "ТП в Бюро Путешествий (Сити)"));
        locationService.addObject(new LocationObjectInstance(2, 68, 0, 2159L, 71L, 307.0d, 63.0, "", "ТП в Сити (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(2, 68, 0, 1619L, 61L, 630.0d, 270.0, "", "ТП в Сити (Бюро Путешествий)"));
        locationService.addObject(new LocationObjectInstance(2, 68, 0, 2037L, 67L, 425.0d, 35.0, "", "ТП в Сити (Корпорация Клубов)"));
        locationService.addObject(new LocationObjectInstance(2, 68, 0, 7855L, 47L, 420.0d, 150.0, "", "ТП в Сити (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 31, 0, 7857L, 47L, 200.0d, 217.0, "", "ТП на Снежную гору (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 23, 0, 7860L, 47L, 526.0d, 362.0, "", "ТП на Главную Площадь (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 49, 0, 1105L, 47L, 595.0d, 190.0, "", "ТП в Больничку (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 63, 0, 2317L, 47L, 211.0d, 18.0, "", "ТП в Школу Магов (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 47, 0, 443L, 49L, 655.0d, -35.0, "", "ТП на Площадь у Больнички (Больничка)"));
        locationService.addObject(new LocationObjectInstance(2, 47, 0, 1752L, 63L, 300.0d, 50.0, "", "ТП на Площадь у Больнички (Школа Магов)"));
        locationService.addObject(new LocationObjectInstance(2, 176, 0, 3852L, 47L, 515.0d, 160.0, "", "ТП на Почту (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(2, 47, 0, 3379L, 176L, -10.0d, 150.0, "", "ТП на Площадь у Больнички (Почта)"));
        locationService.addObject(new LocationObjectInstance(2, 24, 0, 4L, 22L, 310.0d, 140.0, "", "ТП на ППД (Парк)"));
        locationService.addObject(new LocationObjectInstance(2, 27, 0, 267L, 22L, 670.0d, 181.0, "", "ТП на Пляж (Парк)"));
        locationService.addObject(new LocationObjectInstance(2, 24, 0, 7876L, 53L, 20.0d, 330.0, "", "ТП на ППД (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(2, 23, 0, 749L, 53L, 650.0d, 360.0, "", "ТП на Главную Площадь (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(2, 45, 0, 7873L, 38L, 685.0d, 260.0, "", "ТП в Лес (Ромашковая Долина)"));
        locationService.addObject(new LocationObjectInstance(2, 29, 0, 7874L, 38L, 25.0d, 260.0, "", "ТП в Автодром (Ромашковая Долина)"));
        locationService.addObject(new LocationObjectInstance(2, 38, 0, 7863L, 29L, 630.0d, 320.0, "", "ТП в Ромашковую Долину (Автодром)"));
        locationService.addObject(new LocationObjectInstance(2, 27, 0, 7866L, 29L, 50.0d, 280.0, "", "ТП на Пляж (Автодром)"));
        locationService.addObject(new LocationObjectInstance(3, 1, 0, 1748L, 45L, 570.0d, 265.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Дары Леса (Лес)"));
        locationService.addObject(new LocationObjectInstance(22, 0, 0, 4313L, 9L, 700.0d, 411.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Модный журнал (Смешмаг)"));
        locationService.addObject(new LocationObjectInstance(22, 1, 2, 6349L, 9L, 553.0d, 354.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Бот Эллис (Смешмаг)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 1043L, 10L, 220.0d, 300.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Крошки (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 1041L, 10L, 400.0d, 450.0, "", "Лошадка (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 1042L, 10L, 500.0d, 450.0, "", "Мячик (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(3, 12, 0, 291L, 10L, 286.0d, 83.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Поухаживай за крошками (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 344L, 40L, 700.0d, 411.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Стиляга (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 6350L, 40L, 646.0d, 203.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Бот Стефан (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(3, 8, 0, 986L, 40L, 333.0d, 80.0, "", "ТП в игру Студия Моды (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 1052L, 40L, 691.0d, 61.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 1049L, 40L, 208.0d, 47.0, "", "Диван Жюри (Дом Мод)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 221L, 0L, 700.0d, 420.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Все для Крошки (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 309L, 0L, 700.0d, 360.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Возьми крошку себе (Детский сад)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 4851L, 67L, 625.0d, 370.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Бот Ба-босс (Корпорация клубов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 105, 1938L, 67L, 680.0d, 350.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Правила (Корпорация клубов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 1940L, 67L, 287.0d, 32.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Построй свой клуб (Корпорация клубов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 1944L, 67L, 515.0d, 48.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Пригласи артиста (Корпорация клубов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 5282L, 67L, 170.0d, 270.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Объекты на столе (Корпорация клубов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 157, 2161L, 71L, 670.0d, 390.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка За рулем (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 347, 2165L, 71L, 670.0d, 330.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Тюнинг (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 157, 3210L, 71L, 254.0d, 215.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Автомобиль (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 157, 2162L, 71L, 143.0d, 377.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Журнал За рулем (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 347, 2167L, 71L, 510.0d, 20.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Шкаф (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 347, 2164L, 71L, 613.0d, 245.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Журнал Тюнинг (Автосалон)"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 1621L, 61L, 122.0d, 176.0, "", "ТП в фотобудку (Бюро путешествий)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 4328L, 61L, 459.0d, 227.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка паспортов (Бюро путешествий)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 83, 1626L, 61L, 254.0d, 403.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Каталог стран (Бюро путешествий)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 83, 1649L, 61L, 280.0d, 219.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Каталог глобус (Бюро путешествий)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 83, 2985L, 61L, 690.0d, 380.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Вокруг света (Бюро путешествий)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 62, 393L, 47L, 123.0d, 317.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Витрина Шарафоны (Площадь у Больнички)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 15, 403L, 47L, 87.0d, 350.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Банкомат (Площадь у Больнички"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 4334L, 49L, 274.0d, 14.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП на Рентген (Больничка)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 18, 435L, 49L, 434.0d, 16.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Шкафа с вещами (Больничка)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 19, 4320L, 49L, 195.0d, 29.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Каталог Перевязки (Больничка)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 439L, 49L, 478.0d, 102.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Бот Бинтик (Больничка)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 19, 444L, 49L, 358.0d, 41.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Каталог с повязками (Больничка)"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 6267L, 63L, 193.0d, 100.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Игра Урок волшебного карандаша (Школа Магов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 4321L, 63L, 250.0d, 68.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила Урок волшебного карандаша (Школа Магов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 9846L, 63L, 180.0d, 380.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Бот Умникус (Школа Магов)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 6271L, 63L, 404.0d, 62.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Расписание уроков (Школа Магов)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 4005L, 176L, 569.0d, 318.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Отправь открытку другу (Почта)"));
        locationService.addObject(new LocationObjectInstance(3, 10, 0, 1537L, 22L, 27.0d, 341.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Скачки (Парк)(Левые скачки)"));
        locationService.addObject(new LocationObjectInstance(3, 10, 0, 1539L, 22L, 135.0d, 314.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Скачки (Парк)(Средние скачки)"));
        locationService.addObject(new LocationObjectInstance(3, 10, 0, 1538L, 22L, 234.0d, 323.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Скачки (Парк)(Правые скачки)"));
        locationService.addObject(new LocationObjectInstance(3, 9, 0, 2324L, 22L, 152.0d, 157.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Воздушные горки (Парк)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 4317L, 22L, 60.0d, 268.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила игры Скачки (Парк)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 4318L, 22L, 530.0d, 200.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила игры Футбол (Парк)"));
        locationService.addObject(new LocationObjectInstance(3, 11, 0, 1567L, 22L, 470.0d, 160.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Футбол (Парк) (Левый вход)"));
        locationService.addObject(new LocationObjectInstance(3, 11, 0, 1567L, 22L, 580.0d, 158.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Футбол (Парк) (Правый вход)"));
        locationService.addObject(new LocationObjectInstance(3, 2, 0, 759L, 53L, 525.0d, 188.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Бешеный катер (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 26, 6440L, 53L, -31.0d, 88.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Дайвинг-центр (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(2, 0, 0, 865L, 53L, 640.0d, 270.0, "", "ТП в Подводный мир (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 984L, 53L, 667.0d, 155.0, "", "Иконка Загляни под воду (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 751L, 53L, 112.0d, 200.0, "", "Баллоны (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 5408L, 53L, 634.0d, 365.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Иконка Дайв-инфо (Морской порт)"));
        locationService.addObject(new LocationObjectInstance(3, 13, 0, 1101L, 38L, 554.0d, 130.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Вечный Двигатель (Ромашковая долина)(Дом Пина)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 6081L, 38L, 32.0d, 57.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в Домик Лосяша (Ромашковая Долина)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 2153L, 38L, 404.0d, 118.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в Домик Ёжика (Ромашковая долина)"));
        locationService.addObject(new LocationObjectInstance(2, 0, 0, 2335L, 38L, 350.0d, 40.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в Домик Кроша (Ромашковая долина)"));
        locationService.addObject(new LocationObjectInstance(2, 0, 0, 6838L, 38L, 170.0d, 120.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в Домик Нюши (Ромашковая долина)"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 1100L, 38L, 190.0d, 5.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в Домик Карыча (Ромашковая долина)"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 0L, 29L, 84.0d, 165.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП на Формулу Шарарама (Автодром)"));
        locationService.addObject(new LocationObjectInstance(3, 5, 0, 1102L, 27L, 117.0d, 306.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП Смотри в трубу (Пляж)"));
        locationService.addObject(new LocationObjectInstance(2, 29, 0, 7847L, 27L, 292.0d, 54.0, "", "ТП в Автодром (Пляж)"));
        locationService.addObject(new LocationObjectInstance(3, 3, 0, 265L, 27L, 35.0d, 72.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Волейбол (Пляж)"));
        locationService.addObject(new LocationObjectInstance(3, 4, 0, 311L, 27L, 530.0d, -30.0, "", "ТП в игру Кафе (Пляж)"));
        locationService.addObject(new LocationObjectInstance(3, 6, 0, 761L, 27L, 97.0d, 158.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "ТП в игру Секретики (Пляж)"));
        locationService.addObject(new LocationObjectInstance(2, 22, 0, 7848L, 27L, 686.0d, 225.0, "", "ТП в Парк (Пляж)"));
        locationService.addObject(new LocationObjectInstance(4, 0, 0, 4315L, 27L, 53.0d, 164.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Правила игры Секретики (Пляж)"));
        locationService.addObject(new LocationObjectInstance(3, 14, 0, 1099L, 38L, 40.0d, 200.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Шарабудка (Ромашковая долина)"));
        locationService.addObject(new LocationObjectInstance(3, 0, 0, 3177L, 51L, 600.0d, 280.0, "", "Цветок в джунглях"));
        locationService.addObject(new LocationObjectInstance(0, 0, 0, 3178L, 51L, 400.0d, 280.0, "<options><behaviour IsPositionHeld=\"1\" /></options>", "Фея джунглей"));
    }

    private void pushLocations() {
        locationService.addLocation(new Location(47L, 3849L, 400.0d, 250.0d, "Площадь у больнички", false, true));
        locationService.addLocation(new Location(45L, 3993L, 200.0d, 360.0d, "Дремучий лес", true, true));
        locationService.addLocation(new Location(9L, 1035L, 350.0d, 330.0d, "Смешмаг", false, true));
        locationService.addLocation(new Location(10L, 1031L, 530.0d, 280.0d, "Детский сад", false, true));
        locationService.addLocation(new Location(22L, 3990L, 340.0d, 190.0d, "Парк", false, true));
        locationService.addLocation(new Location(23L, 3992L, 300.0d, 380.0d, "Главная площадь", false, true));
        locationService.addLocation(new Location(24L, 2422L, 380.0d, 240.0d, "ППД", false, true));
        locationService.addLocation(new Location(26L, 1630L, 250.0d, 250.0d, "Египет", false, true));
        locationService.addLocation(new Location(27L, 2413L, 660.0d, 240.0d, "Пляж лазурный", false, true));
        locationService.addLocation(new Location(29L, 3996L, 300.0d, 270.0d, "Автодром", false, true));
        locationService.addLocation(new Location(31L, 3999L, 360.0d, 310.0d, "Снежная гора", false, true));
        locationService.addLocation(new Location(32L, 2424L, 200.0d, 190.0d, "Диско", false, true));
        locationService.addLocation(new Location(38L, 1029L, 480.0d, 400.0d, "Ромашковая долина", false, true));
        locationService.addLocation(new Location(40L, 2436L, 200.0d, 300.0d, "Дом мод", false, true));
        locationService.addLocation(new Location(49L, 2411L, 370.0d, 350.0d, "Больничка", false, true));
        locationService.addLocation(new Location(51L, 3164L, 250.0d, 350.0d, "Джунгли", false, true));
        locationService.addLocation(new Location(53L, 3989L, 330.0d, 380.0d, "Порт", false, true));
        locationService.addLocation(new Location(61L, 2415L, 710.0d, 340.0d, "Бюро путешествий", false, true));
        locationService.addLocation(new Location(63L, 6266L, 380.0d, 150.0d, "Школа магов", false, true));
        locationService.addLocation(new Location(67L, 2420L, 570.0d, 320.0d, "Корпорация клубов", false, true));
        locationService.addLocation(new Location(68L, 3994L, 570.0d, 320.0d, "Сити", false, true));
        locationService.addLocation(new Location(71L, 2421L, 300.0d, 125.0d, "Автосалон", false, true));
        locationService.addLocation(new Location(176L, 4010L, 60.0d, 300.0d, "Почта", false, true));
        locationService.addLocation(new Location(226L, 11945L, 370.0d, 370.0d, "Затерянный каньон", false, true));
    }

    private void pushHouseLocations() {
        locationService.addHouseLocation(new HouseLocation(102L, 708, true));
    }

    private void pushBodyParts() {
        List<BodyPart> l = new ArrayList<>();

        l.add(new BodyPart(56L, 56, true, BodyPartType.Body));
        l.add(new BodyPart(60L, 60, true, BodyPartType.Body));
        l.add(new BodyPart(64L, 64, true, BodyPartType.Body));
        l.add(new BodyPart(69L, 69, true, BodyPartType.Body));
        l.add(new BodyPart(73L, 73, true, BodyPartType.Body));
        l.add(new BodyPart(77L, 77, true, BodyPartType.Body));
        l.add(new BodyPart(83L, 83, true, BodyPartType.Body));
        l.add(new BodyPart(89L, 89, true, BodyPartType.Body));

        l.add(new BodyPart(55L, 55, true, BodyPartType.Legs));
        l.add(new BodyPart(62L, 62, true, BodyPartType.Legs));
        l.add(new BodyPart(66L, 66, true, BodyPartType.Legs));
        l.add(new BodyPart(71L, 71, true, BodyPartType.Legs));
        l.add(new BodyPart(75L, 75, true, BodyPartType.Legs));
        l.add(new BodyPart(80L, 80, true, BodyPartType.Legs));
        l.add(new BodyPart(86L, 86, true, BodyPartType.Legs));
        l.add(new BodyPart(92L, 92, true, BodyPartType.Legs));

        l.add(new BodyPart(78L, 78, true, BodyPartType.Ears));
        l.add(new BodyPart(84L, 84, true, BodyPartType.Ears));
        l.add(new BodyPart(90L, 90, true, BodyPartType.Ears));
        l.add(new BodyPart(95L, 95, true, BodyPartType.Ears));
        l.add(new BodyPart(96L, 96, true, BodyPartType.Ears));
        l.add(new BodyPart(97L, 97, true, BodyPartType.Ears));

        l.add(new BodyPart(59L, 59, false, BodyPartType.Eyes));
        l.add(new BodyPart(61L, 61, false, BodyPartType.Eyes));
        l.add(new BodyPart(65L, 65, false, BodyPartType.Eyes));
        l.add(new BodyPart(70L, 70, false, BodyPartType.Eyes));
        l.add(new BodyPart(74L, 74, false, BodyPartType.Eyes));
        l.add(new BodyPart(79L, 79, false, BodyPartType.Eyes));
        l.add(new BodyPart(85L, 85, false, BodyPartType.Eyes));
        l.add(new BodyPart(91L, 91, false, BodyPartType.Eyes));

        l.add(new BodyPart(58L, 58, false, BodyPartType.Nose));
        l.add(new BodyPart(68L, 68, false, BodyPartType.Nose));
        l.add(new BodyPart(82L, 82, false, BodyPartType.Nose));
        l.add(new BodyPart(88L, 88, false, BodyPartType.Nose));
        l.add(new BodyPart(94L, 94, false, BodyPartType.Nose));

        l.add(new BodyPart(57L, 57, false, BodyPartType.Mouth));
        l.add(new BodyPart(67L, 67, false, BodyPartType.Mouth));
        l.add(new BodyPart(81L, 81, false, BodyPartType.Mouth));
        l.add(new BodyPart(87L, 87, false, BodyPartType.Mouth));
        l.add(new BodyPart(93L, 93, false, BodyPartType.Mouth));

        l.add(new BodyPart(63L, 63, false, BodyPartType.Beak));
        l.add(new BodyPart(72L, 72, false, BodyPartType.Beak));
        l.add(new BodyPart(76L, 76, false, BodyPartType.Beak));

        l.add(new BodyPart(99L, 99, false, BodyPartType.Horn));
        l.add(new BodyPart(100L, 100, false, BodyPartType.Horn));
        l.add(new BodyPart(101L, 101, false, BodyPartType.Horn));
        l.add(new BodyPart(102L, 102, false, BodyPartType.Horn));
        l.add(new BodyPart(103L, 103, false, BodyPartType.Horn));

        l.add(new BodyPart(457L, 457, false, BodyPartType.Caps));
        l.add(new BodyPart(458L, 458, false, BodyPartType.Caps));
        l.add(new BodyPart(459L, 459, false, BodyPartType.Caps));
        l.add(new BodyPart(460L, 460, false, BodyPartType.Caps));
        l.add(new BodyPart(461L, 461, false, BodyPartType.Caps));
        l.add(new BodyPart(462L, 462, false, BodyPartType.Caps));
        l.add(new BodyPart(463L, 463, false, BodyPartType.Caps));
        l.add(new BodyPart(464L, 464, false, BodyPartType.Caps));

        l.forEach(i -> avatarInventoryService.saveBodyPart(i));
    }

    private Map<String, Object> decompile(String path) throws IOException {
        FlashDecompiler decompiler = new FlashDecompiler();
        ShockwaveFile file = decompiler.loadFromFile(new File(path));
        DoAction da = (DoAction)file.getTags().stream().filter((p) -> p.getType() == TagType.DoAction).findFirst().get();
        return new Flash2Java(da).convert();
    }

    private void processResources(String swf) throws IOException {
        log.info("Processing resources");

        Map<String, Object> o = decompile(swf);

        FlashMapper.mapToObj(
                o,
                List.of(
                        new OutputObject(MediaResourcePath.class, true, mrtService),
                        new OutputObject(TextResource.class, false, trService),
                        new OutputObject(MediaResource.class, false, mrService),
                        new OutputObject(ResourceObject.class, false, roService)
                )
        );
    }

    private void processCatalogs(String swf) throws IOException {
        log.info("Processing catalogs");
        Map<String, Object> o = decompile(swf);

        FlashMapper.mapToObj(
                o,
                List.of(
                        new OutputObject(GoodTag.class, true, goodTagService),
                        new OutputObject(Good.class, false, goodsService),
                        new OutputObject(Catalog.class, false, catalogService),
                        new OutputObject(GoodMagic.class, false, goodMagicService),
                        new OutputObject(GoodSmile.class, false, goodSmileService),
                        new OutputObject(GoodClubDancefloor.class, false, gcdService)
                )
        );
    }

    private void processBase(String swf) throws IOException {
        log.info("Processing base");

        Map<String, Object> o = decompile(swf);

        FlashMapper.mapToObj(
                o,
                List.of(
                    new OutputObject(MagicAbility.class, false, maService),
                    new OutputObject(Achievement.class, false, achievementService),
                    new OutputObject(Background.class, true, backgroundService),
                    new OutputObject(Library.class, false, libraryService),
                    new OutputObject(SportInventory.class, true, sportInventoryService),
                    new OutputObject(Visa.class, false, visaService),
                    new OutputObject(CatalogObject.class, false, catalogService),
                    new OutputObject(Mission.class, false, missionService),
                    new OutputObject(GAAccount.class, true, gaAccountService),
                    new OutputObject(PriceExchange.class, false, priceExchangeService),
                    new OutputObject(PriceLicense.class, false, priceLicenseService),
                    new OutputObject(PhoneIcon.class, true, phoneIconService),
                    new OutputObject(GameIcon.class, true, gameIconService),
                    new OutputObject(Incompatible.class, false, incompatibleService),
                    new OutputObject(LevelExperience.class, true, levelExperienceService),
                    new OutputObject(Smile.class, false, smileService)
                )
        );
    }
}