
export enum BottleState {
    Empty,
    Some,
    Full,
    Close,
}
export enum GameState {
    GameInit,
    GamePlay,
    GameWin,
    GameLost,
    GameOver,
    GamePause
}

export class Bottle {
    private bodys: number[]
    private index: number
    private state: BottleState
    constructor(index: number) {
        this.index = index
        this.state = BottleState.Empty
        this.bodys = []
    }
    get_index(): number {
        return this.index
    }
    set_index(index: number): void {
        this.index = index
    }
    get_state(): BottleState {
        return this.state
    }
    set_state(state: BottleState): void {
        this.state = state
    }
    get_bodys(): number[] {
        return this.bodys
    }
    set_bodys(bodys: number[]): void {
        this.bodys = bodys
    }
}

export interface IConfigDaoShuiGameBoxData {
    bottles_bodys: number[][]
    max_body_length: number
    max_round: number
    max_more_round: number
}

export interface IDaoShuiGameBoxData {
    /** 所有瓶子 */
    bottles: Bottle[]
    /** 当前选中瓶子index */
    cur_index: number
    /** 目标瓶子index */
    target_index: number
    /** 每个瓶子最大body数 */
    max_body_length: number
    /** 最大操作数 */
    max_round: number
    /** 当前操作数 */
    cur_round: number
    /** 最大额外添加的操作数 */
    max_more_round: number
    /** 当前额外添加的操作数 */
    cur_more_round: number,
    /** 游戏时间 */
    game_time: number
    /** 游戏状态 */
    game_state: GameState
    /** 失败次数 */
    lost_count: number
}

export enum DaoShuiGameEvent {
    /** 游戏胜利 */
    GameWin,
    /** 游戏失利(可复活) */
    GameLost,
    /** 游戏失败 */
    GameOver,
    /** 移动 */
    Move,
}

export interface IGameEventItem {
    /** 游戏时间 */
    game_time: number,
    /** from对象组(多个是为了后期拓展多对象事件) */
    fromIndexs: number[],
    /** to对象组(多个是为了后期拓展多对象事件) */
    toIndexs: number[],
    /** 事件 */
    gameEvent: DaoShuiGameEvent,
    /** 事件数值 */
    eventValues: number[],
    /** 本次动作持续时间(一般和特效时间有关,单位ms) */
    duration: number,
}

export class DaoShuiGameBox implements IDaoShuiGameBoxData {

    /** 所有瓶子 */
    bottles: Bottle[] = []
    /** 当前选中瓶子index */
    cur_index: number = -1
    /** 目标瓶子index */
    target_index: number = -1
    /** 每个瓶子最大body数 */
    max_body_length: number = 3
    /** 最大操作数 */
    max_round: number = 8
    /** 当前操作数 */
    cur_round: number = 0
    /** 最大额外添加的操作数 */
    max_more_round: number = 0
    /** 当前额外添加的操作数 */
    cur_more_round: number = 0
    /** 游戏时间 */
    game_time: number = 0
    /** 游戏状态 */
    game_state: GameState = GameState.GameInit
    /** 失败次数 */
    lost_count: number = 0
    // 临时的
    /** 前一次操作cur的state */
    tmp_pre_cur_bottle_state: BottleState = BottleState.Empty
    /** 前一次操作target的state */
    tmp_pre_target_bottle_state: BottleState = BottleState.Empty

    constructor() {

    }

    public set_config_data(config_data: IConfigDaoShuiGameBoxData) {
        this.max_body_length = config_data.max_body_length
        this.max_more_round = config_data.max_more_round
        this.max_round = config_data.max_round
        for (let i = 0; i < config_data.bottles_bodys.length; i++) {
            const _bottle_bodys = config_data.bottles_bodys[i];
            let _bottle: Bottle = this._body_to_bottle(_bottle_bodys, i)
            this.bottles.push(_bottle)
        }
    }
    private _body_to_bottle(_bottle_bodys: number[], i: number) {
        let state: BottleState = BottleState.Empty
        if (_bottle_bodys.length > 0) {
            if (_bottle_bodys.length == this.max_body_length) {
                state = BottleState.Full
            } else {
                state = BottleState.Some
            }
        }
        let _bottle = new Bottle(i)
        _bottle.set_bodys(_bottle_bodys)
        _bottle.set_state(state)

        // { bodys: _bottle_bodys, index: i, state: state }
        return _bottle
    }

    public get_bottles() {
        return JSON.parse(JSON.stringify(this.bottles))
    }
    public get_bottle_info(index: number) {
        return JSON.parse(JSON.stringify(this.bottles[index]))
    }

    public get_game_time() {
        return this.game_time
    }
    public play() {
        this.game_state = GameState.GamePlay
    }
    public backplay() {
        this.game_state = GameState.GamePlay
    }
    public stop() {
        this.game_state = GameState.GamePause
    }
    public get_game_state() {
        return this.game_state
    }
    public update(dt: number) {
        if (this.game_state == GameState.GamePlay) {
            this.game_time += dt
        }
    }
    // 
    public touch_bottle(index: number): number {
        if (this.cur_index == -1) {
            return this._set_cur_bottle(index)
        }
        if (this.cur_index == index) {
            this.cur_index = -1
            return -1
        }
        return this._set_target_bottle(index)
    }

    private _set_cur_bottle(index: number): number {
        if (this.bottles[index].get_state() == BottleState.Close) {
            this.cur_index = -1 // 已经盖上盖子
        } else {
            if (this.bottles[index].get_state() == BottleState.Empty) {
                this.cur_index = -1 // 空瓶子
            } else {
                this.cur_index = index
            }
        }
        return this.cur_index
    }
    public get_cur_bottle(): Bottle | null {
        if (this.cur_index == -1) {
            return null
        }
        return JSON.parse(JSON.stringify(this.bottles[this.cur_index]))
    }

    public get_target_bottle(): Bottle | null {
        if (this.target_index == -1) {
            return null
        }
        return JSON.parse(JSON.stringify(this.bottles[this.target_index]))
    }
    public move_body(): number[] {
        if (this.cur_index == -1 || this.target_index == -1) {
            // console.error('this.data.cur_index == -1 || this.data.target_index == -1')
            return []
        }
        let move_bodys = this.get_move_bodys(this.cur_index, this.target_index)
        // let gameEventItem: IGameEventItem = {
        //     game_time: this.get_game_time(),
        //     fromIndexs: [this.cur_index],
        //     toIndexs: [this.target_index],
        //     gameEvent: DaoShuiGameEvent.Move,
        //     eventValues: move_bodys,
        //     duration: 1000,
        // }
        // this.saveGameEvent(gameEventItem)
        // this.tmp_pre_cur_bottle_state = this.get_cur_bottle().state
        // this.tmp_pre_target_bottle_state = this.get_target_bottle().state
        this.cur_index = -1
        this.target_index = -1
        return move_bodys
    }
    public check_game_win_or_lost() {
        if (this.check_win() == false) {
            this.check_lost()
        }
        this.cur_round++
    }
    public game_revive() {
        this.game_state = GameState.GamePlay
        this.cur_more_round = this.max_more_round // 加了回合
    }

    private check_win(): boolean {
        // 所有瓶子要么空，要么close
        let is_win = true
        for (let i = 0; i < this.bottles.length; i++) {
            const _bottle = this.bottles[i];
            if (_bottle.get_state() != BottleState.Empty && _bottle.get_state() != BottleState.Close) {
                is_win = false
            }
        }
        if (is_win) {
            this.game_state = GameState.GameWin
        }
        return is_win
    }
    private check_lost() {
        if (this.cur_round >= (this.max_round + this.cur_more_round)) {
            if (this.lost_count == 0) {
                this.lost_count++
                this.game_state = GameState.GameLost
            } else {
                this.game_state = GameState.GameOver
            }
        }
    }

    private _set_target_bottle(index: number): number {
        if (this.bottles[index].get_state() == BottleState.Full ||
            this.bottles[index].get_state() == BottleState.Close) {
            this.target_index = -1
        } else {
            this.target_index = index
        }
        return this.target_index
    }

    private get_move_bodys(fromIndex: number, toIndex: number): number[] {
        let from_bottle: Bottle = this.bottles[fromIndex]
        let to_bottle: Bottle = this.bottles[toIndex]
        let move_bodys: number[] = []
        let del_from_i = -1
        let del_len = 0
        for (let i = from_bottle.get_bodys().length - 1; i > -1; i--) {
            const _body = from_bottle.get_bodys()[i];
            if (to_bottle.get_bodys().length < this.max_body_length) {
                if (move_bodys.length == 0 || move_bodys[move_bodys.length - 1] == _body) {
                    move_bodys.push(_body)
                    // 从 from中移除
                    del_from_i = i
                    to_bottle.get_bodys().push(_body)
                    del_len++
                } else {
                    break;
                }
            } else {
                break;
            }
        }
        if (del_from_i == -1) {
            console.error('del_from_i, del_len', del_from_i, del_len)
        }
        from_bottle.get_bodys().splice(del_from_i, del_len)
        if (from_bottle.get_bodys().length == 0) {
            from_bottle.set_state(BottleState.Empty)
        } else {
            from_bottle.set_state(BottleState.Some)
        }
        if (to_bottle.get_bodys().length == this.max_body_length) {
            to_bottle.set_state(BottleState.Full)
            // 同时查一下是否已经同色
            const uniqueArray = Array.from(new Set(to_bottle.get_bodys()));
            if (uniqueArray.length == 1) {
                to_bottle.set_state(BottleState.Close)
            }
        } else {
            to_bottle.set_state(BottleState.Some)
        }
        return move_bodys
    }

}