class Reel
{
    constructor (config)
    {
        this.parentScene = config.scene;
        this.rm = config.rm;
        
        this.reel = config.reel;//array, [0..n] integers

        this.reelId = config.reelId;
        this.lines = config.lines;
        this.position = config.reelPosition;//position at which reel must stop [0..n-1]

        this.containerX = config.containerX;
        this.containerY = config.containerY;

        this.reelRectWidth = REEL_RECT_WIDTH;//width of reel rect in pixels
        this.reelRectHeight = REEL_RECT_HEIGHT;//height of reel rect in pixels

        this.container = this.parentScene.add.container(this.containerX, this.containerY);
        this.container.setSize(REEL_RECT_WIDTH, REEL_RECT_HEIGHT);

        this.reeltween = new ReelTween({reel: this,
                                    scene: this.parentScene,
                                    duration: config.duration,
                                    backDuration: config.backDuration,
                                    backEase: config.backEase,
                                    spinTime: config.spinTime
                                });


        this.spinTime = 0;
        this.extraSpinTime = 0;

        this.symbolField = [];

        this.winLines = [];

        this.winLine = 0;

        this.haveBreak = false;

        this.sprites = [];
        
        this.winGroup = [];

        this.list = [];

        this.initReelDown();
    }

    initReelDown ()
    {
        for (let i = 0; i < 3; ++i)
        {
            if (++this.position >= this.reel.length)
            {
                this.position = 0;
            }
            
            this.symbolField.push(this.reel[this.position]);
        }

        let spr1 = new SpriteEx(this.parentScene, this, 0, 3 * -REEL_RECT_HEIGHT + 9, this.getSymbolKey());//invisible
        let spr2 = new SpriteEx(this.parentScene, this, 0, 2 * -REEL_RECT_HEIGHT + 9,SYMBOLS[this.symbolField[2]]);//top line
        let spr3 = new SpriteEx(this.parentScene, this, 0, -REEL_RECT_HEIGHT + 9, SYMBOLS[this.symbolField[1]]);//middle line
        let spr4 = new SpriteEx(this.parentScene, this, 0, 9, SYMBOLS[this.symbolField[0]]);//bottom line

        spr1.setVisible(false);

        this.container.add([ spr1 , spr2, spr3, spr4 ]);
        
        this.container.setDepth(CONTAINER_DEPTH_NORMAL + this.reelId);

        this.createContainerClipRect();
        
        this.mask = this.clippingRect.createGeometryMask();

        this.container.setMask(this.mask);
    
        this.reeltween.setDirection(REEL_DOWN);

        this.updateMask();
    }

    createContainerClipRect ()
    {
        if (this.reelId == 0)
        {
            this.clippingRect = this.parentScene.add.rectangle(960 - 2 * REEL_RECT_WIDTH + 26, 592, 280, 600, 0x9966ff).setVisible(false).setAlpha(0.5).setDepth(120);
        }
        else if (this.reelId == 1)
        {
            this.clippingRect = this.parentScene.add.rectangle(960 - REEL_RECT_WIDTH - 8, 592, 424, 600, 0x9966ff).setVisible(false).setAlpha(0.5).setDepth(120);
        }
        else if (this.reelId == 2)
        {
            this.clippingRect = this.parentScene.add.rectangle(960, 592, 424, 600, 0x9966ff).setVisible(this.false).setAlpha(0.5).setDepth(120);
        }
        else if (this.reelId == 3)
        {
            this.clippingRect = this.parentScene.add.rectangle(960 + REEL_RECT_WIDTH + 8, 592, 424, 600, 0x9966ff).setVisible(false).setAlpha(0.5).setDepth(120);
        }
        else if(this.reelId == 4)
        {
            this.clippingRect = this.parentScene.add.rectangle(960 + REEL_RECT_WIDTH * 2 - 16, 592, 260, 600, 0x9966ff).setVisible(false).setAlpha(0.5).setDepth(120);
        }

        this.shapeX = this.clippingRect.x;
        this.shapeY = this.clippingRect.y;
    }

    resizeMask (y1, y2)
    {
        if (this.reelId == 0)
        {
            this.clippingRect.setSize(280, 600 + y1 + y2);
        }
        else if (this.reelId == 1 || this.reelId == 2 || this.reelId == 3)
        {
            this.clippingRect.setSize(424, 600 + y1 + y2);
        }
        else
        {
            this.clippingRect.setSize(260, 600 + y1 + y2);
        }
    }

    updateMask ()
    {
        let y1 = 70;
        let y2 = 70;

        this.container.list[0].setVisible(false);

        this.resizeMask(y1, y2);

        this.container.setDepth(CONTAINER_DEPTH_OVER + this.reelId);
    }

    getSymbolKey ()
    {
        if (++this.position >= this.reel.length)
        {
            this.position = 0;
        }

        return SYMBOLS[this.reel[this.position]];
    }

    update (time, delta) 
    {
    }

    startSpin ()
    {
        if (this.sprites[3] != undefined)
        {
            this.sprites[3].setVisible(true);
        }
        else
        {
            this.container.list[0].setVisible(true);
        }

        if (this.list.length > 0)
        {
            this.container.list = this.list;

            this.list = [];
        }

        this.reeltween.renderReel();
    }

    normalSpin()
    {
        this.reeltween.normalSpin(this.spinTime, this.extraSpinTime);
    }

    fastSpin()
    {
        this.reeltween.fastSpin();
    }

    beginSpin ()
    {
        this.destroyAnimations();

        this.resizeMask(0, 0);

        if (this.parentScene.isPortraitMode())
        {
            this.clippingRect.setPosition(this.shapeX - 420, this.shapeY + 336);
        }

        this.animationsComplete = 0;

        this.container.setDepth(CONTAINER_DEPTH_NORMAL + this.reelId);

        this.startSpin();
    }

    endSpin()
    {
        this.state = REEL_STATE_STOPPED;

        this.resetContainer();

        this.list = [...this.container.list];

        this.sprites[0] = this.container.list[1];
        this.sprites[1] = this.container.list[2];
        this.sprites[2] = this.container.list[3];
        this.sprites[3] = this.container.list[0];
       
        if (this.sprites[3].visible)
        {
            this.sprites[3].setVisible(false);
        }

        this.rm.reelStopped(this.reelId);
    }

    createAnimation (v, key)
    {
        switch (key)
        {
            case "cherry":
            case "lemon":
            case "orange":                
            case "plum":
            case "bell":
            case "grape":
            case "melon":
            case "seven":
                {
                    this.sprites[v].setTextureKey(key);

                };break;

            case "break":
                {
                    if (this.sprites[v].anims.currentAnim == null) 
                    {
                        this.sprites[v].setTextureKey(key, SYMBOL_ANIMATION);

                        let   anim = this.parentScene.anims.create({
                                key: this.reelId + "_breakPlayAnim_" + v,
                                frames: this.parentScene.anims.generateFrameNumbers("break"),
                                frameRate: 9,
                                repeat: 0
                            });
        
                        this.sprites[v].anims.currentAnim = anim;
                    }
                };break;
        }
    }
    
    playBreakAnim () 
    {
        this.parentScene.sndBreak[0].play();
    
        this.sprites.forEach((sprite) =>
        {
            if (sprite.getTextureKey() == "break") 
            {            
                this.parentScene.tweens.add({
                    targets: sprite,
                    scale: { from: 1, to: 1.5 },  
                    ease: "Quad.easeInOut",    
                    duration: 500,             
                    yoyo: true,                
                    repeat: 1,
                    onComplete: () => 
                    {
                        this.parentScene.sndBreak[1].play();
                        this.parentScene.time.delayedCall(130 , () => 
                        {
                            this.breakSymbolAnim(sprite);
                        });
                    }                
                });
                
                this.container.bringToTop(sprite);
            }
        });
    }
    
    breakSymbolAnim (sprite) 
    {
        sprite.setTextureKey("break");

        this.parentScene.anims.create({
                key: "breakAnim",
                frames: this.parentScene.anims.generateFrameNumbers("break"),
                frameRate: 9,
                repeat: 0
            });

        sprite.play("breakAnim");

        sprite.once("animationcomplete", () => 
        {
            sprite.setFrame(0);
            this.parentScene.tweens.killTweensOf(sprite);  
        }, this);
    }

    createLineAnimations ()
    {
        let symbolField = [...this.symbolField];
        symbolField = symbolField.reverse();
        
        for (let i = 0; i < this.winLines.length; ++i)
        {
            if (this.reelId < this.winLines[i].len)
            {
                let v = this.lines[this.winLines[i].id][this.reelId] + 1;
                let key = SYMBOLS[symbolField[v]];

                this.createAnimation(v, key);
            }
        }
    }

    createScatterAnimation (symbol, scatterInfo)
    {
        for (let i = 0; i < scatterInfo.length; ++i)
        {
            if (scatterInfo[i] == 1)
            {
                this.createAnimation(i, SYMBOLS[symbol]);
                return;
            }
        }
    }

    stopAnimations ()
    {
        this.sprites.forEach(sprite => {sprite.stopAnimation();});
    }

    destroyAnimations ()
    {
        this.sprites.forEach(sprite => {sprite.destroyAnimation();});
    }

    setWinLine (winLine)
    {
        this.winLine = winLine;
    }

    playLineAnimation ()
    {
        let len = this.winLines[this.winLine].len;

        if (this.reelId < len)
        {
            let v = this.lines[this.winLines[this.winLine].id][this.reelId] + 1;

            this.sprites[v].playAnimation(0);

            this.container.bringToTop(this.sprites[v]);

            if (this.haveWild)
            {
               this.container.setDepth(CONTAINER_DEPTH_WITH_WILD + this.reelId);
            }
        }
    }

    playScatterAnimation (symbol)
    {
        let nmAnims = 0;

        for (let i = 0; i < this.sprites.length - 1; ++i)
        {
            if (this.sprites[i].getTextureKey() == SYMBOLS[symbol])
            {
                this.sprites[i].playAnimation();
                
                this.container.bringToTop(this.sprites[i]);

                ++nmAnims;
            }
        }

        return nmAnims;
    }

    playGroupAnimations ()
    {
        let nmAnims = 0;

        for (let i = 0; i < this.winGroup.length; ++i)
        {
            if (this.winGroup[i] == 1)
            {
                this.sprites[i].playAnimation();

                this.container.bringToTop(this.sprites[i]);

                ++nmAnims;
            }
        }

        return nmAnims;
    }

    animationComplete ()
    {
        this.rm.animationComplete();
    }

    resetSymbolsZOrder ()
    {
        this.container.bringToTop(this.sprites[0]);
        this.container.bringToTop(this.sprites[1]);
        this.container.bringToTop(this.sprites[2]);

        this.container.setDepth(CONTAINER_DEPTH_OVER + this.reelId);
    }

    setSymbolField (symbolField)
    {
        this.symbolField = [...symbolField].reverse(); 
    }

    setWinLines (winLines)
    {
        this.winLines = winLines;

        this.winLine = 0;
    }

    setWinGroup (winGroup)
    {
        this.winGroup = [...winGroup];
    }

    setState (state)
    {
        this.state = state;
    }

    getState ()
    {
        return this.state;
    }

    setSpinTime (time, extraTime)
    {
        this.spinTime = time;
        this.extraSpinTime = extraTime;
    }

    stop ()
    {
        this.rm.hideStopBtn();

        this.fastSpin();
    }

    errStop ()
    {
        this.reeltween.errStop();
    }

    setVisible (v)
    {
        this.container.setVisible(v);
    }

    resetContainer ()
    {
        if (this.parentScene.isLandscapeMode())
        {
            this.container.setPosition(this.containerX, this.containerY);
        }
        else
        {
            this.container.setPosition(this.containerX - 420 , this.containerY + 336);
        }

        this.container.list[0].setPosition(0, 3 * -REEL_RECT_HEIGHT + 9);
        this.container.list[1].setPosition(0, 2 * -REEL_RECT_HEIGHT + 9);
        this.container.list[2].setPosition(0, -REEL_RECT_HEIGHT + 9);
        this.container.list[3].setPosition(0, 9);
    }

    onOrientationChange ()
    {
        if (this.parentScene.isLandscapeMode())
        {
            this.container.setPosition(this.containerX, this.containerY);
            this.clippingRect.setPosition(this.shapeX, this.shapeY);
        }
        else
        {
            this.container.setPosition(this.containerX - 420 , this.containerY + 336);
            this.clippingRect.setPosition(this.shapeX - 420, this.shapeY + 336);
        }

        if (this.parentScene.isLandscapeMode())
        {
            if (this.parentScene.tweens.isTweening(this.container))
            {
                this.container.list[0].setPosition(this.container.list[0].x, this.container.list[0].y - 336);
                this.container.list[1].setPosition(this.container.list[1].x, this.container.list[1].y - 336);
                this.container.list[2].setPosition(this.container.list[2].x, this.container.list[2].y - 336);
                this.container.list[3].setPosition(this.container.list[3].x, this.container.list[3].y - 336);
            }
        }
        else
        {
            if (this.parentScene.tweens.isTweening(this.container))
            {
                this.container.list[0].setPosition(this.container.list[0].x, this.container.list[0].y + 336);
                this.container.list[1].setPosition(this.container.list[1].x, this.container.list[1].y + 336);
                this.container.list[2].setPosition(this.container.list[2].x, this.container.list[2].y + 336);
                this.container.list[3].setPosition(this.container.list[3].x, this.container.list[3].y + 336);
            }
        }
    }
}
