import {
    randInt
} from './_rand.js';

import {
    tile
} from './_tile.js';

import {
    Fight,
    FightException
} from './fight.js';

import {
    boardConfig as boards
} from './board/config.js';

import {
    Character
} from './character.js';

import {
    Stuff
} from './stuff/stuff.js';

import {
    Exit
} from './board/exit.js';


/** @type {board} */
var board = {
    _addTo: undefined,
    _boardId: -1,
    boardCfg: [],
    _freeTiles: [  ],
    _exits: [ ],
    _characters: [
        /* hero, villain, monster, animal, civilian, ... */
    ],
    _stuff: [
        /* medipack, drink, food, weapon ... */
    ],
    isInitialized: false,
    init: function () {
        this._addTo = document.getElementById('playground');
        this._stuff = [];
        this._characters = [];
        this._doors = [];
        // this.loadNextBoard();
        this.isInitialized = true;
    },
    /**
     * @memberOf {board}
     * moves a character on the board
     */
    move: function (char, dir) {
        let x = char.x();
        let y = char.y();
        let nextX = x;
        let nextY = y;

        switch (dir) {
            case 'up':
                nextX = nextX - 1;
                break;
            case 'down':
                nextX = nextX + 1;
                break;
            case 'left':
                nextY = nextY - 1;
                break;
            case 'right':
                nextY = nextY + 1;
                break;
        }
        let nextType = this.whatsOnPos(nextX, nextY);
        if (nextType instanceof Character) {
            console.log('we encountered a %o / %o at %o/%o', nextType.getType(), nextType, nextX, nextY);
            this.fight(char, nextType);
            this.drawBoard();
            return nextType.getType();
        } else if (nextType instanceof Stuff) {

            console.log('found some stuff:%o', nextType);

            if (window.confirm('Soll "'+ nextType.getName() + '" hinzugefügt werden?')) {
                this.boardCfg[x][y] = '-';
                char.x(nextX).y(nextY);
                char.addStuff(nextType);
                this.boardCfg[nextX][nextY] = char;
            }

            this.drawBoard();
            return nextType.getType();
        } else if (nextType instanceof Exit) {
            console.log('found an Exit:%o', nextType);
            if (this.isHeroLeft()) {
                console.log('!!!!!!!!! load next board!!');
                this.game.loadNextBoard(this);
            }
            this.drawBoard();
            return nextType.getType();
        } else {
            this._fight = null;
        }
        char.addLife(1);
        // console.log('moving to  nextType %o', nextType);
        switch (nextType) {
            case 'block':
                // boink
                console.log('we will hit our head');
                return false;

            case 'free':
                // boink
           //     console.log('we will move to %o/%o', nextX, nextY);
                this.boardCfg[x][y] = '-';
                char.x(nextX).y(nextY);
                this.boardCfg[nextX][nextY] = char;
                break;

            default:
                console.warn('this should never happen');
                break;
        }
        this.drawBoard();
        // updating all character boards
        this._characters.forEach(function (c) {
            console.log('calling %o.html.update()', c.getType());
            c.html.update();
        });

        return true;
    },
    _fight: null,
    /** @memberOf {board} */
    fight: function (attacker, defender) {
        if (this._fight === null) {
            this._fight = new Fight(attacker, defender);
            // console.log('CREATING Fight!!! %o vs. %o\n    Fight:%o', attacker, defender, this._fight);
        }
        try {
            // console.warn('Fighting');
            this._fight.fight();
            // console.dir(this._fight)
            attacker.html.update();
            defender.html.update();
        } catch (e) {
            // console.log(e);
            if (e instanceof FightException) {
                console.warn('Fight ended => loser:%o\n   WINNER:%o', e.loser, e.winner);
                let lX = e.loser.x();
                let lY = e.loser.y();

                e.winner.setExperience(e.winner.getExperience() + 10);

                //                this.boardCfg[lX][lY] = '-';
                this._fight = null;
            }
        }
    },
    _chracterAlreadyIn: function (char) {
        let flag = false;
        this._characters.forEach(function (c, id) {
            if (char === c) {
                flag = id;
            }
        });
        return flag;
    },
    addCharacter: function (c) {
        if (!this._chracterAlreadyIn(c)) {
            this._characters.push(c);
        }
        // console.warn(c.x(), c.y());
        let pos;
        if (c.x() === false && c.y() === false) {
            pos = this.getFreePos(true);
            // console.log('free:%o', pos);
        } else {
            console.log('exits:%o', this._exits[0]);
            pos = this._exits[0];
        }
        c.x(pos.x)
            .y(pos.y);
        this.boardCfg[pos.x][pos.y] = c;
        return this;
    },
    isHeroLeft: function () {
        if (this._characters && this._characters.length === 1 && this._characters[0].getType() === 'hero') {
            return true;
        }
        return false;
    },
    removeCharacter: function (c) {
        let cId = this._chracterAlreadyIn(c);
        if (cId === false) {
            console.warn('could not find character on board');
            return this;
        }
        this._characters.splice(cId, 1);
        let x = c.x();
        let y = c.y();
        this.boardCfg[x][y] = '-';
//        c.html.board.innerHTML = '<p class="ko-message">KO</p>';
        return this;
    },
    addStuff: function (s) {

        let pos = this.getFreePos(true);
        this.boardCfg[pos.x][pos.y] = s;
        return this;
    },
    loadBoard: function (boardCfg) {
        this.boardCfg = boardCfg;
        this.boardCfg.forEach(function (row, idx, bo) {
            row.forEach(function (tile, idy, ro) {
                let content = this.whatsOnPos(idx, idy);
                if (content === 'free') {
                    this._freeTiles.push({
                        x: idx,
                        y: idy
                    });
                } else if (content === 'exit') {
                    let e = new Exit(this, idx, idy);
                    boardCfg[idx][idy] = e;
                    // console.log('created exit => idx:%o / idy:%o => Exit(%o)', idx, idy, e  );
                    this._exits.push({x: idx, y: idy});
                } else if (typeof content !== 'string' && (content.getType() === 'villain' || content.getType() === 'hero')) {
                    this.boardCfg[idx][idy] = '-';
                    this._freeTiles.push({
                        x: idx,
                        y: idy
                    });
                }
            }, this);
        }, this);
        console.log(this._exits);
        this.init();
        return this;
    },
    whatsOnPos: function (x, y) {
        let tile = this.boardCfg[x][y];
        if (typeof tile !== 'string') {
            return tile;
        }
        if (staticMap.hasOwnProperty(tile)) {
            return staticMap[tile].toString();
        }
        return false;
    },
    randPosition: function () {
        let randX = randInt(this.boardCfg[0].length);
        let randY = randInt(this.boardCfg[0][0].length);
        return {
            x: randX,
            y: randY
        };
    },
    getFreePos: function (remove) {
        let pos;
        let i = 0;
        remove = remove || false;
        i = randInt(this._freeTiles.length);
        pos = this._freeTiles[i];
        if (remove === true) {
            this._freeTiles.splice(i, 1);
        }
        return pos;
    },
    drawBoard: function () {
        /** @type {HTMLElement} */
        let where = this._addTo;
        //where.innerHTML = '<div class="icon-spin6 animate-spin centered"></div>';
        let b = this.boardCfg;
        let table = document.createElement('table');
        table.className = 'pure-table pure-table-bordered board';
        for (let i = 0; i < b.length; i += 1) {
            let line = document.createElement('tr');
            for (let j = 0; j < b[i].length; j += 1) {
                let el = document.createElement('td');
                let type = this.whatsOnPos(i, j);
                tile(type, el, {"x": i, "y": j});
                line.appendChild(el);
            }
            table.appendChild(line);
        }
        where.innerHTML = '';
        where.appendChild(table);
        // console.log(this._characters);
        this._characters.forEach(function (c) {
            // console.log('calling %o.html.update()', c.getType());
            c.html.update();
        });
    }
};

const staticMap = {
    "-": {
        toString: function () { return 'free'; }
    },
    "b": {
        toString: function () { return 'block'; }
    },
    "w": {
        toString: function () { return 'weapon'; }
    },
    "e": {
        toString: function () { return 'exit'; }
    }
};


export {
    board
};