import * as NativeUI from '../libs/NativeUI';
import * as Data from './data';

const Menu = NativeUI.Menu;
const UIMenuItem = NativeUI.UIMenuItem;
const UIMenuListItem = NativeUI.UIMenuListItem;
const UIMenuCheckboxItem = NativeUI.UIMenuCheckboxItem;
const BadgeStyle = NativeUI.BadgeStyle;
const Point = NativeUI.Point;
const ItemsCollection = NativeUI.ItemsCollection;
const Color = NativeUI.Color;
const Font = NativeUI.Font;
var screenRes = mp.game.graphics.getScreenResolution(0, 0);

const creatorCoords = {
    camera: new mp.Vector3(265.6026, -1340.2378, 25.000),
    cameraLookAt: new mp.Vector3(266.472, -1339.1357, 25.000)
};

const localPlayer = mp.players.local;

export default function charSurgery(globalData: IGlobalData) {

    var creatorCamera: CameraMp;
    var activeSurgery: boolean = false;
    var saveCharacter: PlayerCharacterData;
    var characterData: PlayerCharacterData;

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    var creatorMainMenu: NativeUI.Menu;
    var debugString = [0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0];

    mp.events.add("render", () => {
        mp.game.graphics.drawText(debugString.toString(), [0.5, 0.1],
            {
                font: 4,
                color: [255, 255, 255, 255],
                scale: [0.5, 0.5],
                outline: true,
                centre: false
            })
    });

    mp.events.add("toggleSurgery", (jsonCharacterData: string) => {
        if (!mp.cameras.exists(creatorCamera)) {
            activeSurgery = true;
            debugString[0] = 1;
            characterData = JSON.parse(jsonCharacterData);
            saveCharacter = characterData;
            debugString[1] = 2;
            loadCharacterData();
            debugString[2] = 3;
            creatorCamera = mp.cameras.new("creatorCamera", creatorCoords.camera, new mp.Vector3(0, 0, 0), 45);
            creatorCamera.pointAtCoord(creatorCoords.cameraLookAt.x, creatorCoords.cameraLookAt.y, creatorCoords.cameraLookAt.z);
            creatorCamera.setActive(true);

            globalData.InMenu = true;
            globalData.InMenu = true;
            mp.gui.chat.show(false);
            mp.game.ui.displayRadar(false);
            mp.game.ui.displayHud(false);
            localPlayer.clearTasksImmediately();
            localPlayer.freezePosition(true);
            mp.game.cam.renderScriptCams(true, false, 0, true, false);
            debugString[3] = 4;
            applyCreatorOutfit();
            getCharacterMainMenu();
        }
    });

    var loadedFeatures;
    var loadedAppearance;
    var loadedAppearanceOpacity;

    function loadCharacterData() {
        loadedFeatures = [
            characterData.NoseWidth,
            characterData.NoseBottomHeight,
            characterData.NoseTipLength,
            characterData.NoseBridgeDepth,
            characterData.NoseTipHeight,
            characterData.NoseBroken,
            characterData.BrowHeight,
            characterData.BrowDepth,
            characterData.CheekboneHeight,
            characterData.CheekboneWidth,
            characterData.CheekDepth,
            characterData.EyeSize,
            characterData.LipThickness,
            characterData.JawWidth,
            characterData.JawShape,
            characterData.ChinHeight,
            characterData.ChinDepth,
            characterData.ChinWidth,
            characterData.ChinIndent,
            characterData.NeckWidth
        ];
        loadedAppearance = [
            characterData.Blemishes,
            characterData.FacialHair,
            characterData.Eyebrows,
            characterData.Ageing,
            characterData.Makeup,
            characterData.Blush,
            characterData.Complexion,
            characterData.SunDamage,
            characterData.Lipstick,
            characterData.Freckles,
            characterData.ChestHair
        ];
        loadedAppearanceOpacity = [
            characterData.BlemishesOpacity,
            characterData.FacialHairOpacity,
            characterData.EyebrowsOpacity,
            characterData.AgeingOpacity,
            characterData.MakeupOpacity,
            characterData.BlushOpacity,
            characterData.ComplexionOpacity,
            characterData.SunDamageOpacity,
            characterData.LipstickOpacity,
            characterData.FrecklesOpacity,
            characterData.ChestHairOpacity
        ];
    }

    //HAUPTMENÜ
    function getCharacterMainMenu(): NativeUI.Menu {

        creatorMainMenu = new Menu("Chirurg", "", new Point(0, screenRes.y / 3), null, null);
        creatorMainMenu.Visible = false;
        debugString[4] = 5;
        var genderItem = new UIMenuListItem("Geschlecht", "~r~Dies setzt deine Einstellungen zurück.", new ItemsCollection(["Männlich", "Weiblich"]));
        creatorMainMenu.AddItem(genderItem);
        genderItem.Index = characterData.Gender == false ? 0 : 1;
        debugString[5] = 6;
        var parentsItem = new UIMenuItem("Eltern", "Eltern des Charakters.");
        creatorMainMenu.AddItem(parentsItem);
        creatorMainMenu.BindMenuToItem(getParentsMenu(creatorMainMenu), parentsItem);
        debugString[6] = 7;
        var featureItem = new UIMenuItem("Gesichtsmerkmale", "Gesichtsmerkmale des Charakters.")
        creatorMainMenu.AddItem(featureItem);
        creatorMainMenu.BindMenuToItem(getFeaturesMenu(creatorMainMenu), featureItem);
        debugString[7] = 8;
        var appearanceItem = new UIMenuItem("Aussehen", "Aussehen des Charakters.")
        creatorMainMenu.AddItem(appearanceItem);
        creatorMainMenu.BindMenuToItem(getAppearanceMenu(creatorMainMenu), appearanceItem);
        debugString[8] = 9;
        var hairAndColorItem = new UIMenuItem("Haar & Farben", "Haare & Farben deines Charakters.")
        creatorMainMenu.AddItem(hairAndColorItem);
        creatorMainMenu.BindMenuToItem(getHairAndColorMenu(creatorMainMenu), hairAndColorItem);
        debugString[9] = 10;

        //Charakterdrehung
        var angles = [];
        for (var i = -180.0; i <= 180.0; i += 5.0) angles.push(i.toFixed(1));
        var angleItem = new UIMenuListItem("Drehung", "", new ItemsCollection(angles));
        creatorMainMenu.AddItem(angleItem);

        var saveItem = new UIMenuItem("Operieren", "Der Chirurg macht die Arbeit, lehn dich zurück");
        saveItem.BackColor = new Color(13, 71, 161);
        saveItem.HighlightedBackColor = new Color(25, 118, 210);
        creatorMainMenu.AddItem(saveItem);

        creatorMainMenu.ListChange.on((item, listIndex) => {
            if (item === genderItem) {
                saveCharacter.Gender = <boolean>listIndex;
                mp.events.callRemote("creator_GenderChange", listIndex);

                setTimeout(() => {
                    localPlayer.clearTasksImmediately();
                    applyCreatorOutfit();
                    angleItem.Index = 0;
                    resetParents();
                    resetFeatures();
                    resetAppearance();

                }, 200);
            } else if (item === angleItem) {
                localPlayer.setHeading(parseFloat(angleItem.SelectedValue));
                localPlayer.clearTasksImmediately();
            }
        });

        creatorMainMenu.MenuClose.on(() => {
            leaveCreator();
        });
        creatorMainMenu.Visible = true;
        return creatorMainMenu;        
    }

    var fatherItem: NativeUI.UIMenuListItem;
    var motherItem: NativeUI.UIMenuListItem;
    var similarityItem: NativeUI.UIMenuListItem;
    var skinSimilarityItem: NativeUI.UIMenuListItem;
    var creatorParentsMenu: NativeUI.Menu;

    //MENÜ FÜR ELTERN
    function getParentsMenu(parentMenu: NativeUI.Menu): NativeUI.Menu {
        var similarities = [];
        for (var i = 0; i <= 100; i++) similarities.push(i + "%");
        
        creatorParentsMenu = new Menu("Eltern", "", new Point(0, screenRes.y / 3), null, null);
        creatorParentsMenu.Visible = false;

        fatherItem = new UIMenuListItem("Vater", "Dem Charakter sein Vadda.", new ItemsCollection(Data.fatherNames));
        creatorParentsMenu.AddItem(fatherItem);
        //fatherItem.Index = characterData.Father;

        motherItem = new UIMenuListItem("Mutter", "Dem Charakter seine Mudda.", new ItemsCollection(Data.motherNames));
        creatorParentsMenu.AddItem(motherItem);
        //motherItem.Index = characterData.Mother;

        similarityItem = new UIMenuListItem("\u00c4hnlichkeit", "\u00c4hnlichkeit zu den Eltern.\n(niedriger = feminin, h\u00f6her = maskulin)", new ItemsCollection(similarities));
        creatorParentsMenu.AddItem(similarityItem);
        //similarityItem.Index = characterData.Similarity;

        skinSimilarityItem = new UIMenuListItem("Hautfarbe", "Hautfarben \u00c4hnlichkeit zu den Eltern.\n(niedriger = Mutter, h\u00f6her = Vater)", new ItemsCollection(similarities));
        creatorParentsMenu.AddItem(skinSimilarityItem);
        //skinSimilarityItem.Index = characterData.SkinSimilarity;

        var resetItem = new UIMenuItem("Zurücksetzen", "~r~Setzt die Eltern zurück. :'(");
        creatorParentsMenu.AddItem(resetItem);

        creatorParentsMenu.ItemSelect.on((item, index) => {
            if (item == resetItem) {
                resetParents();
            }
        });

        creatorParentsMenu.ListChange.on((item, listIndex) => {
            updateParents();
        });

        debugString[10] = 11;
        
        return creatorParentsMenu;
    }

    function updateParents() {
        localPlayer.setHeadBlendData(
            // shape
            Data.mothers[motherItem.Index],
            Data.fathers[fatherItem.Index],
            0,

            // skin
            Data.mothers[motherItem.Index],
            Data.fathers[fatherItem.Index],
            0,

            // mixes
            similarityItem.Index * 0.01,
            skinSimilarityItem.Index * 0.01,
            0.0,

            false
        );
    }

    function resetParents(refresh = false) {
        fatherItem.Index = 0;//characterData.Father.valueOf();
        motherItem.Index = 0;//characterData.Mother.valueOf();
        similarityItem.Index = (characterData.Gender == false) ? 100 : 0; //characterData.Similarity.valueOf();//
        skinSimilarityItem.Index = (characterData.Gender == false) ? 100 : 0;//characterData.SkinSimilarity.valueOf();

        updateParents();
        if (refresh) creatorParentsMenu.RefreshIndex();
    }

    //Menü für Gesichtsmerkmale
    var featureItems = [];
    function getFeaturesMenu(parentMenu: NativeUI.Menu): NativeUI.Menu {
        
        var features = [];
        for (var i = -1.0; i <= 1.01; i += 0.01) features.push(i.toFixed(2));

        var creatorFeaturesMenu = new Menu("Gesichtsmerkmale", "", new Point(0, screenRes.y / 3), null, null);
        creatorFeaturesMenu.Visible = false;
        debugString[6] = 7;
        for (var i = 0; i < Data.featureNames.length; i++) {
            var tempFeatureItem = new UIMenuListItem(Data.featureNames[i], "", new ItemsCollection(features));
            tempFeatureItem.Index = 100;
            featureItems.push(tempFeatureItem);
            creatorFeaturesMenu.AddItem(tempFeatureItem);
            //tempFeatureItem.Index = loadedFeatures[i];
        }

        var resetItem = new UIMenuItem("Zurücksetzen", "~r~Setzt Gesichtsmerkmale zurück.");
        creatorFeaturesMenu.AddItem(resetItem);

        creatorFeaturesMenu.ItemSelect.on((item, index) => {
            switch (item) {
                case resetItem:
                    resetFeatures();
                    break;
            }
        });

        creatorFeaturesMenu.ListChange.on((item, listIndex) => {
            updateFaceFeature(featureItems.indexOf(item));
        });

        debugString[11] = 12;
        return creatorFeaturesMenu;
    }

    function resetFeatures() {
        for (let i = 0; i < Data.featureNames.length; i++) {
            featureItems[i].Index = 100;
            updateFaceFeature(i);
        }
    }

    function updateFaceFeature(index) {
        localPlayer.setFaceFeature(index, parseFloat(featureItems[index].SelectedValue));
    }

    var appearanceItems = [];
    var appearanceOpacityItems = [];
    //Menü für Aussehen
    function getAppearanceMenu(parentMenu: NativeUI.Menu): NativeUI.Menu {

        
        var opacities = [];
        for (var i = 0; i <= 100; i++) opacities.push(i + "%");

        var creatorAppearanceMenu = new Menu("Aussehen", "", new Point(0, screenRes.y / 3), null, null);
        creatorAppearanceMenu.Visible = false;
        debugString[7] = 8;
        for (var i = 0; i < Data.appearanceNames.length; i++) {
            var items = [];
            for (var j = 0, max = mp.game.ped.getNumHeadOverlayValues(i); j <= max; j++) items.push(Data.appearanceItemNames[i][j] === undefined ? j.toString() : Data.appearanceItemNames[i][j]);

            var tempAppearanceItem = new UIMenuListItem(Data.appearanceNames[i], "", new ItemsCollection(items));
            appearanceItems.push(tempAppearanceItem);
            creatorAppearanceMenu.AddItem(tempAppearanceItem);
            //tempAppearanceItem.Index = loadedAppearance[i];

            var tempAppearanceOpacityItem = new UIMenuListItem(Data.appearanceNames[i] + " Transparenz", "", new ItemsCollection(opacities));
            tempAppearanceOpacityItem.Index = 100;
            appearanceOpacityItems.push(tempAppearanceOpacityItem);
            creatorAppearanceMenu.AddItem(tempAppearanceOpacityItem);
            //tempAppearanceOpacityItem.Index = loadedAppearanceOpacity[i];
        }

        var resetItem = new UIMenuItem("Zurücksetzen", "~r~Setzt das Aussehen zurück.");
        creatorAppearanceMenu.AddItem(resetItem);

        creatorAppearanceMenu.ItemSelect.on((item, index) => {
            switch (item) {
                case resetItem:
                    resetAppearance();
                    break;
            }
        });

        creatorAppearanceMenu.ListChange.on((item, listIndex) => {
            var idx = (creatorAppearanceMenu.CurrentSelection % 2 === 0) ? (creatorAppearanceMenu.CurrentSelection / 2) : Math.floor(creatorAppearanceMenu.CurrentSelection / 2);
            updateAppearance(idx);
        });
        debugString[12] = 13;
        return creatorAppearanceMenu;
    }

    function updateAppearance(index) {
        var overlayID = (appearanceItems[index].Index === 0) ? 255 : appearanceItems[index].Index - 1;
        localPlayer.setHeadOverlay(index, overlayID, appearanceOpacityItems[index].Index * 0.01, colorForOverlayIdx(index), 0);
    }

    function resetAppearance(refresh = false) {
        for (var i = 0; i < Data.appearanceNames.length; i++) {
            appearanceItems[i].Index = loadedAppearance[i];
            appearanceOpacityItems[i].Index = loadedAppearanceOpacity[i];
            updateAppearance(i);
        }
    }

    // color arrays
    var hairColors = [];
    for (var i = 0; i < Data.maxHairColor; i++) hairColors.push(i.toString());

    var blushColors = [];
    for (var i = 0; i < Data.maxBlushColor; i++) blushColors.push(i.toString());

    var lipstickColors = [];
    for (var i = 0; i < Data.maxLipstickColor; i++) lipstickColors.push(i.toString());

    //Menü für Haar & Farben
    function getHairAndColorMenu(parentMenu: NativeUI.Menu): NativeUI.Menu {

        var creatorHairMenu = new Menu("Haar & Farben", "", new Point(0, screenRes.y / 3), null, null);
        creatorHairMenu.Visible = false;
        debugString[8] = 9;
        var eyebrowColorItem = new UIMenuListItem("Augenbrauen Farbe", "Farbe deiner Augenbrauen", new ItemsCollection(hairColors));
        creatorHairMenu.AddItem(eyebrowColorItem);

        var beardColorItem = new UIMenuListItem("Farbe der Gesichtsbehaarung", "Farbe deiner Gesichtsbehaarung", new ItemsCollection(hairColors));
        creatorHairMenu.AddItem(beardColorItem);

        var eyeColorItem = new UIMenuListItem("Augenfarbe", "Farbe deiner Augen", new ItemsCollection(Data.eyeColors));
        creatorHairMenu.AddItem(eyeColorItem);

        var blushColorItem = new UIMenuListItem("Rouge", "Farbe des Rouges.", new ItemsCollection(blushColors));
        creatorHairMenu.AddItem(blushColorItem);

        var lipstickColorItem = new UIMenuListItem("Lippenstift Farbe", "Farbe deines Lippenstifts.", new ItemsCollection(lipstickColors));
        creatorHairMenu.AddItem(lipstickColorItem);

        var chestHairColorItem = new UIMenuListItem("Farbe der Brustbehaarung", "Farbe deiner Brustbehaarung", new ItemsCollection(hairColors));
        creatorHairMenu.AddItem(chestHairColorItem);

        var cancelItem = new UIMenuItem("Zurücksetzen", "~r~Zurücksetzen von Haar & Farben");
        creatorHairMenu.AddItem(cancelItem);

        creatorHairMenu.ItemSelect.on((item, index) => {
            switch (item) {
                case cancelItem:
                    eyebrowColorItem.Index = characterData.EyebrowColor;
                    beardColorItem.Index = characterData.BeardColor;
                    eyeColorItem.Index = characterData.EyeColor;
                    blushColorItem.Index = characterData.BlushColor;
                    lipstickColorItem.Index = characterData.LipstickColor;
                    chestHairColorItem.Index = characterData.ChestHairColor;
                    updateHairAndColors();
                    break;
            }
        });

        creatorHairMenu.ListChange.on((item, listIndex) => {
            switch (creatorHairMenu.CurrentSelection) {

                case 0: // eyebrow color
                    localPlayer.setHeadOverlayColor(2, 1, listIndex, 0);
                    break;

                case 1: // facial hair color
                    localPlayer.setHeadOverlayColor(1, 1, listIndex, 0);
                    break;

                case 2: // eye color
                    localPlayer.setEyeColor(listIndex);
                    break;

                case 3: // blush color
                    localPlayer.setHeadOverlayColor(5, 2, listIndex, 0);
                    break;

                case 4: // lipstick color
                    localPlayer.setHeadOverlayColor(8, 2, listIndex, 0);
                    break;

                case 5: // chest hair color
                    localPlayer.setHeadOverlayColor(10, 1, listIndex, 0);
                    break;
            }
        });
        debugString[13] = 14;
        return creatorHairMenu;
    }

    function updateHairAndColors() {
        localPlayer.setEyeColor(saveCharacter.EyeColor);
        localPlayer.setHeadOverlayColor(1, 1, saveCharacter.BeardColor, 0);
        localPlayer.setHeadOverlayColor(2, 1, saveCharacter.EyebrowColor, 0);
        localPlayer.setHeadOverlayColor(5, 2, saveCharacter.BlushColor, 0);
        localPlayer.setHeadOverlayColor(8, 2, saveCharacter.LipstickColor, 0);
        localPlayer.setHeadOverlayColor(10, 1, saveCharacter.ChestHairColor, 0);
    }

    function colorForOverlayIdx(index) {
        var color;

        switch (index) {
            case 1:
                color = saveCharacter.BeardColor;
                break;

            case 2:
                color = saveCharacter.EyebrowColor;
                break;

            case 5:
                color = saveCharacter.BlushColor;
                break;

            case 8:
                color = saveCharacter.LipstickColor;
                break;

            case 10:
                color = saveCharacter.ChestHairColor;
                break;

            default:
                color = 0;
        }

        return color;
    }

    function applyCreatorOutfit() {
        if (saveCharacter.Gender === false) {
            localPlayer.setDefaultComponentVariation();
            localPlayer.setComponentVariation(3, 15, 0, 2);
            localPlayer.setComponentVariation(4, 21, 0, 2);
            localPlayer.setComponentVariation(6, 34, 0, 2);
            localPlayer.setComponentVariation(8, 15, 0, 2);
            localPlayer.setComponentVariation(11, 15, 0, 2);
        } else {
            localPlayer.setDefaultComponentVariation();
            localPlayer.setComponentVariation(3, 15, 0, 2);
            localPlayer.setComponentVariation(4, 10, 0, 2);
            localPlayer.setComponentVariation(6, 35, 0, 2);
            localPlayer.setComponentVariation(8, 15, 0, 2);
            localPlayer.setComponentVariation(11, 15, 0, 2);
        }
    }
    
    function leaveCreator() {
        activeSurgery = false;
        mp.gui.chat.show(true);
        mp.game.ui.displayRadar(true);
        mp.game.ui.displayHud(true);
        localPlayer.freezePosition(false);
        mp.game.cam.renderScriptCams(false, false, 0, true, false);
        creatorCamera.destroy(true);
        mp.events.callRemote("surgeryLeave");
        globalData.InMenu = false;
        globalData.InMenu = false;
    }
}