import { writable } from "svelte/store";

import { createBuilding, createHero, createQuest } from "./create";
import worldmap from "./data/worldmap";
import { getTilesAtDistance, Hex } from "./hexgrid";
import type { BuildingType, HeroType, QuestType, RegionType, ResourcesType } from "./types";
import { getKeysAsNumbers, shuffle } from "./utils";


type Board = {
    [key: number]: {
        [key: number]: number;
    }
}


export interface VillageState {
    buildings: BuildingType[];
    units: {
        [key: string]: number;
    },
    resources: ResourcesType;
    villageTiles: Board;
    outsideTiles: Board;
    worldmap: RegionType[];
    heroes: HeroType[];
    quests: QuestType[];
    victory: boolean;
}


export const DEFAULT_TILE = -1;
export const VILLAGE_TILE = -2;


function getInitialVillageBoard() {
    const board: Board = {
        0: { 0: DEFAULT_TILE },
    };
    for (let i = 1; i <= 2; i++) {
        getTilesAtDistance(i).forEach(tile => {
            if (board[tile.y] === undefined) {
                board[tile.y] = {};
            }

            board[tile.y][tile.x] = DEFAULT_TILE;
        });
    }
    return board;
}


function getInitialOutsideBoard() {
    const board: Board = {
        0: { 0: VILLAGE_TILE },
    };
    for (let i = 1; i <= 2; i++) {
        getTilesAtDistance(i).forEach(tile => {
            if (board[tile.y] === undefined) {
                board[tile.y] = {};
            }

            board[tile.y][tile.x] = DEFAULT_TILE;
        });
    }
    return board;
}


function getInitialWorldmap(): RegionType[] {
    return worldmap.map((r, index) => {
        const region = r as RegionType;
        return {
            ...region,
            state: {
                index,
            },
        };
    });
}


function getInitialQuests(): QuestType[] {
    return [
        createQuest(1),
        createQuest(1),
        createQuest(1),
    ];
}


function getInitialState() {
    const state: VillageState = {
        buildings: [],
        units: {},
        resources: {
            wood: 60,
            stone: 60,
            iron: 60,
            food: 50,
            culture: 0,
        },
        villageTiles: getInitialVillageBoard(),
        outsideTiles: getInitialOutsideBoard(),
        worldmap: getInitialWorldmap(),
        heroes: [
            createHero(),
        ],
        quests: getInitialQuests(),
        victory: false,
    };

    // Create the Town hall.
    const townhall = createBuilding('townhall');
    state.villageTiles[0][0] = townhall.id;
    state.buildings.push(townhall);

    // Create all the resource buildings.
    const resourceBuildingTypes: Array<string> = shuffle([
        'woodcutter', 'woodcutter', 'woodcutter', 'woodcutter',
        'mine', 'mine', 'mine', 'mine',
        'pit', 'pit', 'pit', 'pit',
        'field', 'field', 'field', 'field', 'field', 'field',
    ]);
    getKeysAsNumbers(state.outsideTiles).forEach(y => {
        getKeysAsNumbers(state.outsideTiles[y]).forEach(x => {
            if (state.outsideTiles[y][x] !== DEFAULT_TILE) {
                return;
            }

            const type = resourceBuildingTypes.pop();
            if (type === undefined) {
                throw new Error("Not enough building types for outside resource buildings");
            }
            const newBuilding = createBuilding(type);
            newBuilding.tile = new Hex(x, y);
            newBuilding.level = 20; //newBuilding.type === 'field' ? 1 : 10;
            state.outsideTiles[y][x] = newBuilding.id;
            state.buildings.push(newBuilding);
        });
    });

    return state;
}


const village = writable<VillageState>(getInitialState());


function reset() {
    village.set(getInitialState());
}


export default {
    ...village,
    reset,
};
