module DragDrop {
    enum Types {
        OneToMany,
        ManyToOne,
        OneToOne,
        BigContainer

    }
    export class DragDrop extends Base.BasicGroup {
        private isExam = false;
        private allPaired = true;
        private groupsEnabled = true;
        private GameData: any;
        private dragElements: any[];
        private containers: any[];
        private containersGroups: any[];
        constructor(game, name, x, y, json) {
            super(game, name, x, y, json);

        }
        init(json) {
            super.init(json);
            this.GameData = json.GameData;

        }
        preload() {
            super.preload();
            this.game.load.onLoadComplete.addOnce(this.create, this);
            this.loadGraphics();
            this.game.load.start();

        }
        create() {
            if (this.json.isStandalone) {
                super.create();
            }

            this.createStaticElements();
            this.createContainerElements();
            this.createDragableElements();
            this.loadGroups();
            this.initOptions();

        }
        initOptions() {
            if (this.GameData.AllPaired === undefined || this.GameData.AllPaired === null) {
                this.allPaired = true;
            } else {
                this.allPaired = this.GameData.AllPaired;
            }

        }
        //load Images
        loadGraphics() {
            for (var i = 0; i < this.GameData.Graphics.length; i++)
                this.game.load.image(this.GameData.Prefix + this.GameData.Graphics[i].key, this.GameData.Graphics[i].src);
        }
        
       

        //create static elements frames and elements non interactive
        createStaticElements() {
            if (this.GameData.StaticElements.Options.isGrid) {
                var opt = this.GameData.StaticElements.Options;
                var orientation;
                if (opt.Orientation === undefined || opt.Orientation === null) {
                    orientation = true;
                } else {
                    orientation = opt.Orientation;
                }
                var positions = EU.generateGridPositions(opt.Columns, opt.Rows, opt.MaxWidth, opt.MaxHeight, opt.Spacing, opt.Spacing, opt.StartingPos.x, opt.StartingPos.y, orientation);


                for (var i = 0; i < this.GameData.StaticElements.el.length; i++) {
                    var el = this.game.add.image(positions[i].x, positions[i].y, this.GameData.Prefix + this.GameData.StaticElements.el[i].key);
                    this.addChild(el);

                }
            } else {

                for (var i = 0; i < this.GameData.StaticElements.el.length; i++) {
                    var el = this.game.add.image(this.GameData.StaticElements.el[i].pos.x, this.GameData.StaticElements.el[i].pos.y, this.GameData.Prefix + this.GameData.StaticElements.el[i].key);
                    this.addChild(el);

                }
            }

        }
        //create container elements, add to table of containers
        createContainerElements() {
            this.containers = [];
            var el;
            var i = 0;
            if (this.GameData.ContainerElements.Options.isGrid) {
                var opt = this.GameData.ContainerElements.Options;
                var positions = EU.generateGridPositions(opt.Columns, opt.Rows, opt.MaxWidth, opt.MaxHeight, opt.Spacing, opt.Spacing, opt.StartingPos.x, opt.StartingPos.y, true);

                for (var i = 0; i < this.GameData.ContainerElements.el.length; i++) {
                    el = this.game.add.image(positions[i].x, positions[i].y, this.GameData.Prefix + this.GameData.ContainerElements.el[i].key);
                    el.name = this.GameData.ContainerElements.el[i].name;
                    this.containers.push({
                        "el": el,
                        "startPos": {
                            "x": el.position.x,
                            "y": el.position.y
                        },
                        "name": el.name,
                        "dragElementName": ""
                    });
                    this.addChild(el);

                }
            }
            else {
                for (i = 0; i < this.GameData.ContainerElements.el.length; i++) {
                    el = this.game.add.image(this.GameData.ContainerElements.el[i].pos.x, this.GameData.ContainerElements.el[i].pos.y, this.GameData.Prefix + this.GameData.ContainerElements.el[i].key);
                    el.name = this.GameData.ContainerElements.el[i].name;
                    this.containers.push({
                        "el": el,
                        "startPos": {
                            "x": el.position.x,
                            "y": el.position.y
                        },
                        "name": el.name,
                        "dragElementName": ""
                    });

                    this.addChild(el);
                }
            }

        }


        private onInputUpBigContainer(el: Phaser.Sprite, pointer) {

            //BIG CONTAINER
            var index = this.getCorrespondingContainerIndex(el);
            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {

                    /* if (this.containers[i].dragElementName === "") {
                         this.containers[i].dragElementName = el.name;
                     } else {
 
                         var oldDrag = this.getDragElementByName(this.containers[i].dragElementName);
                         oldDrag.pairedWith = "";
                         oldDrag.el.bringToTop();
 
                         this.containers[i].dragElementName = el.name;
 
                     }*/
                    this.dragElements[index].paired = true;
                    this.dragElements[index].pairedWith = this.containers[i].name;
                    this.checkCompleted(this.allPaired);
                    return;
                }
            }

            this.dragElements[index].paired = false;
            this.dragElements[index].pairedWith = "";
            EU.Log("game completion set to 0");
            EU.setGameCompletion(this.parent, 0);
            var tw = this.game.add.tween(el);
            tw.to({ x: this.dragElements[index].startPos.x, y: this.dragElements[index].startPos.y }, 500, Phaser.Easing.Circular.InOut);
            tw.start();
        }

        //create dragable elements and set OnInput method 
        createDragableElements() {

            this.dragElements = [];
            if (this.GameData.DragableElements.Options.isGrid) {
                var opt = this.GameData.DragableElements.Options;
                var positions = EU.shuffleArray(EU.generateGridPositions(opt.Columns, opt.Rows, opt.MaxWidth, opt.MaxHeight, opt.Spacing, opt.Spacing, opt.StartingPos.x, opt.StartingPos.y, true));

                for (var i = 0; i < this.GameData.DragableElements.el.length; i++) {
                    var el = this.game.add.image(positions[i].x, positions[i].y, this.GameData.Prefix + this.GameData.DragableElements.el[i].key);
                    el.inputEnabled = true;
                    el.name = this.GameData.DragableElements.el[i].name;
                    el.input.enableDrag();
                    switch (this.GameData.DragType) {
                        case "OneToOne":
                            el.events.onInputUp.add(this.onInputUp, this);
                            el.events.onInputDown.add(this.onInputDown, this);
                            break;
                        case "GroupsWithOrder":
                            el.events.onInputUp.add(this.onInputUpGroupsWithOrder, this);
                            el.events.onInputDown.add(this.onInputDownGroupsWithOrder, this);
                        case "BigContainer":
                            el.events.onInputDown.add(this.onInputDownBigContainer, this);
                            el.events.onInputUp.add(this.onInputUpBigContainer, this);
                    }

                    this.dragElements.push({
                        "el": el,
                        "startPos": {
                            "x": el.position.x,
                            "y": el.position.y
                        },
                        "paired": false,
                        "correctContainer": this.GameData.DragableElements.el[i].correctContainer,
                        "correctGroup": this.GameData.DragableElements.el[i].correctGroup,
                        "pairedWith": ""
                    });
                    this.addChild(el);

                }
            } else {

                for (var i = 0; i < this.GameData.DragableElements.el.length; i++) {
                    var el = this.game.add.image(this.GameData.DragableElements.el[i].pos.x, this.GameData.DragableElements.el[i].pos.y, this.GameData.Prefix + this.GameData.DragableElements.el[i].key);
                    el.inputEnabled = true;
                    el.name = this.GameData.DragableElements.el[i].name;
                    el.input.enableDrag();
                    switch (this.GameData.DragType) {
                        case "OneToOne":
                            el.events.onInputUp.add(this.onInputUp, this);
                            el.events.onInputDown.add(this.onInputDown, this);
                            break;
                        case "GroupsWithOrder":
                            el.events.onInputUp.add(this.onInputUpGroupsWithOrder, this);
                            el.events.onInputDown.add(this.onInputDownGroupsWithOrder, this);
                        case "BigContainer":
                            el.events.onInputDown.add(this.onInputDownBigContainer, this);
                            el.events.onInputUp.add(this.onInputUpBigContainer, this);
                        default:
                            el.events.onInputUp.add(this.onInputUp, this);
                            el.events.onInputDown.add(this.onInputDown, this);
                    }

                    this.dragElements.push({
                        "el": el,
                        "startPos": {
                            "x": el.position.x,
                            "y": el.position.y
                        },
                        "paired": false,
                        "correctContainer": this.GameData.DragableElements.el[i].correctContainer,
                        "correctGroup": this.GameData.DragableElements.el[i].correctGroup,
                        "pairedWith": ""
                    });
                    this.addChild(el);

                }
            }



        }
       
        //load groups of containers into containersGroup array
        loadGroups() {
            this.groupsEnabled = this.GameData.GroupsEnabled;
            if (this.groupsEnabled) {

                this.containersGroups = [];
                if (this.GameData.ContainerGroups != undefined);
                for (var i = 0; i < this.GameData.ContainerGroups.length; i++) {

                    var tmp = [];
                    for (var x = 0; x < this.GameData.ContainerGroups[i].el.length; x++) {
                        tmp.push(this.getContainerByName(this.GameData.ContainerGroups[i].el[x].name));
                    }
                    var z = { "name": this.GameData.ContainerGroups[i].name, el: tmp };
                    this.containersGroups.push(z);
                }
            }
        }

        private onInputDownGroupsWithOrder(el: Phaser.Sprite, pointer) {
            this.getDragElementByName(el.name).pairedWith = "";
            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {
                    this.containers[i].dragElementName = "";
                }
            }
            el.bringToTop();
        }
        private onInputUpGroupsWithOrder(el: Phaser.Sprite, pointer) {
            var index = this.getCorrespondingContainerIndex(el);
            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {

                    if (this.containers[i].dragElementName === "") {
                        this.containers[i].dragElementName = el.name;
                    } else {

                        var oldDrag = this.getDragElementByName(this.containers[i].dragElementName);
                        oldDrag.pairedWith = "";
                        oldDrag.el.bringToTop();
                        var returnTween = this.game.add.tween(oldDrag.el);
                        returnTween.to({ x: oldDrag.startPos.x, y: oldDrag.startPos.y }, 500, Phaser.Easing.Circular.InOut);
                        returnTween.start();

                        this.containers[i].dragElementName = el.name;

                    }
                    el.x = this.containers[i].startPos.x;
                    el.y = this.containers[i].startPos.y;
                    this.dragElements[index].paired = true;
                    this.dragElements[index].pairedWith = this.containers[i].name;
                    this.checkCompletedGroupsWithOrder(this.allPaired);
                    return;
                }
            }

            this.dragElements[index].paired = false;
            this.dragElements[index].pairedWith = "";
            EU.Log("game completion set to 0");
            EU.setGameCompletion(this.parent, 0);
            var tw = this.game.add.tween(el);
            tw.to({ x: this.dragElements[index].startPos.x, y: this.dragElements[index].startPos.y }, 500, Phaser.Easing.Circular.InOut);
            tw.start();
        }

        //zwraca tablice z indexem prawidlowego orderu i prawidlowym indexem w szeregu
        private findCorrectOrders(el) {
            var arr = [];
            for (var i = 0; i < this.GameData.DragCorrectOrder.length; i++) {
                for (var j = 0; j < this.GameData.DragCorrectOrder[i].el.length; j++) {
                    if (el === this.GameData.DragCorrectOrder[i].el[j].name) {
                        arr.push(j);


                    }
                }
            }
            return arr;
        }
        private findContainerCorrectOrder(el) {
            var arr = [];
            for (var i = 0; i < this.GameData.ContainerGroups.length; i++) {
                for (var j = 0; j < this.GameData.ContainerGroups[i].el.length; j++) {
                    if (el === this.GameData.ContainerGroups[i].el[j].name) {
                        arr.push(j);
                    }
                }
            }
            return arr;
        }

        private checkCompletedGroupsWithOrder(allPaired) {
            EU.Log("game completion set to 0");
            EU.setGameCompletion(this.parent, 0);
            var i = 0;
            //if all objects must be paired
            for (var i = 0; i < this.dragElements.length; i++) {
                console.log(this.dragElements[i].pairedWith);
            }
            if (allPaired)
                for (i = 0; i < this.dragElements.length; i++) {
                    if (!this.dragElements[i].paired)
                        return false;
                }
            for (var i = 0; i < this.dragElements.length; i++) {
                var x = this.findCorrectOrders(this.dragElements[i].el.name);
                var y = this.findContainerCorrectOrder(this.dragElements[i].pairedWith);
                console.log("x " + x);
                console.log("y " + y);
                for (var j = 0; j < x.length; j++)
                    if (x[j] !== y[j])
                        return false;
            }




            




        

            /*
            //if groups are enabled check every element in group
            if (this.groupsEnabled) {
                for (i = 0; i < this.dragElements.length; i++) {
                    if (!this.isElementInCorrectGroup(this.dragElements[i]))
                        return false;
                }
            }
            else {
                for (i = 0; i < this.dragElements.length; i++) {
                    if (this.dragElements[i].correctContainer !== this.dragElements[i].pairedWith) {
                        return false;
                    }

                }

            }
            */
            EU.setGameCompletion(this.parent, 1);

            EU.Log("completed");
        }
        //input 

        private onInputDownBigContainer(el: Phaser.Sprite, pointer) {

            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {
                    this.containers[i].dragElementName = "";
                }
            }
            el.bringToTop();
        }

        private onInputDown(el: Phaser.Sprite, pointer) {
            this.getDragElementByName(el.name).pairedWith = "";
            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {
                    this.containers[i].dragElementName = "";
                }
            }
            el.bringToTop();
        }
        private onInputUp(el: Phaser.Sprite, pointer) {
            var index = this.getCorrespondingContainerIndex(el);
            for (var i = 0; i < this.containers.length; i++) {
                if (this.overlap(el, this.containers[i].el)) {

                    if (this.containers[i].dragElementName === "") {
                        this.containers[i].dragElementName = el.name;
                    } else {

                        var oldDrag = this.getDragElementByName(this.containers[i].dragElementName);
                        oldDrag.pairedWith = "";
                        oldDrag.el.bringToTop();
                        var returnTween = this.game.add.tween(oldDrag.el);
                        returnTween.to({ x: oldDrag.startPos.x, y: oldDrag.startPos.y }, 500, Phaser.Easing.Circular.InOut);
                        returnTween.start();

                        this.containers[i].dragElementName = el.name;

                    }
                    el.x = this.containers[i].startPos.x;
                    el.y = this.containers[i].startPos.y;
                    this.dragElements[index].paired = true;
                    this.dragElements[index].pairedWith = this.containers[i].name;
                    console.log(this.GameData.DragType);
                    if (this.GameData.DragType === "NotAllPaired")
                        this.checkCompletedFilledContainers();
                    else {
                        this.checkCompleted(this.allPaired);
                    }
                   
                    return;
                }
            }

            this.dragElements[index].paired = false;
            this.dragElements[index].pairedWith = "";
            EU.Log("game completion set to 0");
            EU.setGameCompletion(this.parent, 0);
            var tw = this.game.add.tween(el);
            tw.to({ x: this.dragElements[index].startPos.x, y: this.dragElements[index].startPos.y }, 500, Phaser.Easing.Circular.InOut);
            tw.start();
        }
        //AllPaired if true every drag element must have container
        //
        private checkCompleted(allPaired) {
            EU.Log("game completion set to 0");
            EU.setGameCompletion(this.parent, 0);
            var i = 0;
            //if all objects must be paired
            if (allPaired)
                for (i = 0; i < this.dragElements.length; i++) {
                    if (!this.dragElements[i].paired)
                        return false;
                }
            
            //if groups are enabled check every element in group
            if (this.groupsEnabled) {
                for (i = 0; i < this.dragElements.length; i++) {
                    if (!this.isElementInCorrectGroup(this.dragElements[i])) {
                      
                        return false;
                    }

                }
            }
            else {
                for (i = 0; i < this.dragElements.length; i++) {
                    if (this.dragElements[i].correctContainer !== this.dragElements[i].pairedWith) {
                       
                        return false;
                    }

                }

            }

            EU.setGameCompletion(this.parent, 1);

            EU.Log("completed");
        }



        checkCompletedFilledContainers() {
            EU.Log(this.containers);
            for (var i = 0; i < this.containers.length; i++) {
                if (this.containers[i].dragElementName === "") {
                   
                    return false;
                }
            }
            for (var i = 0; i < this.containers.length; i++) {
                var temp = this.getDragElementByName(this.containers[i].dragElementName).correctContainer;
                EU.Log(temp);
                if (temp !== this.containers[i].name) {
                  
                    return false;
                    }
            }
            EU.setGameCompletion(this.parent, 1);

            EU.Log("completed");
            return true;
        }




        private overlap(a, b) {

            var bA = a.getBounds();
            var bB = b.getBounds();
            return Phaser.Rectangle.intersects(bA, bB);
        }


        private isElementInCorrectGroup(el) {
            for (var i = 0; i < this.containersGroups.length; i++) {
                //TODO REFACTOR
                if (el.correctGroup === "")
                    return true;
                if (this.containersGroups[i].name === el.correctGroup) {
                    for (var j = 0; j < this.containersGroups[i].el.length; j++) {
                        if (this.containersGroups[i].el[j].name === el.pairedWith)
                            return true;
                    }
                }
            }
            return false;
        }
        //return container by name
        private getContainerByName(name) {
            for (var i = 0; i < this.containers.length; i++)
                if (this.containers[i].el.name === name)
                    return this.containers[i].el;
        }
        private getDragElementByName(name) {
            for (var i = 0; i < this.dragElements.length; i++)
                if (this.dragElements[i].el.name === name)
                    return this.dragElements[i];
        }
        //return index of drag Element
        private getCorrespondingContainerIndex(el) {
            for (var i = 0; i < this.dragElements.length; i++) {
                if (el === this.dragElements[i].el)
                    return i;
            }
        }


    }

}


//JSON
//
//     "DragType": "OneToOne",
//"Graphics":
//[
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_01.png", "key": "01" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_02.png", "key": "02" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_03.png", "key": "03" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_04.png", "key": "04" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_05.png", "key": "05" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_06.png", "key": "06" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_07.png", "key": "07" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_08.png", "key": "08" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_image1.png", "key": "image1" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_image2.png", "key": "image2" },
//    { "src": "Graphics/WorkCards/OS_I_2/1/OS_kp_I_2_drag_empty.png", "key": "c" },
//],
//"StaticElements": {
//    "el": [
//        { "key": "image1", "pos": { "x": 30, "y": 50 } },
//        { "key": "image2", "pos": { "x": 30, "y": 400 } }
//    ],
//    "Options": {
//        "isGrid": false,
//        "StartingPos": { "x": 20, "y": 30 },
//        "Columns": 4,
//        "Rows": 2,
//        "Spacing": 10
//    }
//},

//"DragableElements": {
//    "el": [
//        { "key": "01", "pos": { "x": 3, "y": 3 }, "name": "O_1", "correctContainer": "C_1", "correctGroup": "group1" },
//        { "key": "02", "pos": { "x": 3, "y": 3 }, "name": "O_2", "correctContainer": "C_1", "correctGroup": "group2" },
//        { "key": "03", "pos": { "x": 3, "y": 3 }, "name": "O_3", "correctContainer": "C_1", "correctGroup": "group2" },
//        { "key": "04", "pos": { "x": 3, "y": 3 }, "name": "O_4", "correctContainer": "C_1", "correctGroup": "group1" },
//        { "key": "05", "pos": { "x": 3, "y": 3 }, "name": "O_5", "correctContainer": "C_1", "correctGroup": "group2" },
//        { "key": "06", "pos": { "x": 3, "y": 3 }, "name": "O_6", "correctContainer": "C_1", "correctGroup": "group1" },
//        { "key": "07", "pos": { "x": 3, "y": 3 }, "name": "O_7", "correctContainer": "C_1", "correctGroup": "group2" },
//        { "key": "08", "pos": { "x": 3, "y": 3 }, "name": "O_8", "correctContainer": "C_1", "correctGroup": "group1" },
//    ],
//    "Options": {
//        "isGrid": true,
//        "StartingPos": { "x": 1050, "y": 0 },
//        "Columns": 2,
//        "Rows": 4,
//        "Spacing": 10,
//        "MaxWidth": 250,
//        "MaxHeight" : 200

//    }
//},
//"ContainerElements": {
//    "el": [
//        { "key": "c", "pos": { "x": 0, "y": 150 }, "name": "C_1" },
//        { "key": "c", "pos": { "x": 250, "y": 150 }, "name": "C_2" },
//        { "key": "c", "pos": { "x": 500, "y": 150 }, "name": "C_3" },
//        { "key": "c", "pos": { "x": 750, "y": 150 }, "name": "C_4" },
//        { "key": "c", "pos": { "x": 0, "y": 500 }, "name": "C_5" },
//        { "key": "c", "pos": { "x": 250, "y": 500 }, "name": "C_6" },
//        { "key": "c", "pos": { "x": 500, "y": 500 }, "name": "C_7" },
//        { "key": "c", "pos": { "x": 750, "y": 500 }, "name": "C_8" },
//    ],
//    "Options": {
//        "isGrid": false,
//        "StartingPos": { "x": 20, "y": 300 },
//        "Columns": 4,
//        "Rows": 2,
//        "Spacing": 10

//    }
//},
//"ContainerGroups":
//[
//    { "name": "group1", "el": [{ "name": "C_1" }, { "name": "C_2" }, { "name": "C_3" }, { "name": "C_4" }] },
//    { "name": "group2", "el": [{ "name": "C_5" }, { "name": "C_6" }, { "name": "C_7" }, { "name": "C_8" }] }
//]

//            };




/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////            FORMAT JSONA           ////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//    JSON = {
//              completeText: "caly tekst do wyswietlenia",
//              searched: [["znak lub wyraz", (true/false || true szuka znaku lub wyrazu oddzielonego spacjami, kropka, myslnikiem lub cudzyslowiem; false szuka podciągu)], [], []]    
//           } 



