import * as I from "../types/types";
import { config } from "./config";
import * as State from "./state";
import * as Cart from "./cart";
import * as CartButtons from "./cartButtons";

export function getSeats(): I.JSCSeats {
    const seatmapXML: any = config.state.seatmapXML;
    const pricescaleArr: I.SeatmapPricescale[] = seatmapXML.seatmap[0].pricescale_config[0].pricescale;
    let seatmapInitSeats: I.JSCSeats = {};

    for (let key in pricescaleArr) {
        const seatsObj: I.JSCSeats2 = {
            "classes": `_${pricescaleArr[key].id[0]}`,
            "seatsObj": pricescaleArr[key]
        }
        const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
        seatmapInitSeats[seatsKey] = seatsObj;
    }

    return seatmapInitSeats;
}

export function activateSeatsBySectionID(inValue: string): void {
    const seatmapXML: any = config.state.seatmapXML;
    const seatmap: any = config.state.seatmap;
    const pricescaleArr: I.SeatmapPricescale[] = seatmapXML.seatmap[0].pricescale_config[0].pricescale;

    const seatsArr: string[] | undefined = pricescaleArr.find(arr => {
        return arr.id[0] === inValue;
    })?.mask[0].split(",");

    seatmap.status(seatsArr, "available");
}

export function getRowsNaming(): string[] {
    const seatmapXML: any = config.state.seatmapXML;
    const layout: I.SeatmapLayout = seatmapXML.seatmap[0].layouts[0].layout[0];
    const height: number = parseInt(layout.height[0]);
    const namingArr: string[] = Array.from({ length: height }, (_) => "");
    const rowsArr: I.LayoutRow2[] = layout.rows[0].row;

    rowsArr.forEach(element => {
        const index: number = parseInt(element.y_cell_coord[0]);
        const seatsArr: string[] = element.seats[0].split("|");
        const seatArr: string[] = splitSeatStr(seatsArr[0]);
        const row: string = seatArr[4];
        namingArr[index] = row;
    });

    return namingArr;
}

export function generateMap(): string[] {
    const seatmapXML: any = config.state.seatmapXML;
    const layout: I.SeatmapLayout = seatmapXML.seatmap[0].layouts[0].layout[0];
    const rows: I.LayoutRow2[] = layout.rows[0].row;
    const pricescaleArr: I.SeatmapPricescale[] = seatmapXML.seatmap[0].pricescale_config[0].pricescale;
    const availabilityArr: I.JSCAvailability = seatmapXML.seatmap[0].view_modes[0].view_mode[0].availability[0];

    // Form: arrMatrix[Y][X]
    let arrMatrix: string[][] = createArrMatrix(
        parseInt(layout.height[0]),
        parseInt(layout.width[0]),
        "_"
    );

    arrMatrix = enterSeatsInMatrix(rows, arrMatrix, pricescaleArr, availabilityArr);
    return arrMatrix.map(element => element.join(""));
}

export function generateLegend(inNode: string): I.JSCLegend {
    const seatmapXML: any = config.state.seatmapXML;
    const venueXML: I.VenueXML = config.state.inVenueXML!;
    const pricescaleArr: I.SeatmapPricescale[] = seatmapXML.seatmap[0].pricescale_config[0].pricescale;
    const venuePricescaleArr: I.Pricescale2[] = venueXML.venue[0].pricescales[0].pricescale;

    return <I.JSCLegend>{
        node: jQuery(inNode),
        items: createLegendItems(pricescaleArr, venuePricescaleArr)
    }
}



export function setUnavailableSeats(): void {
    const seatmapXML: any = config.state.seatmapXML;
    const seatmap: any = config.state.seatmap;
    const availabilityArr: I.JSCAvailability = seatmapXML.seatmap[0].view_modes[0].view_mode[0].availability[0];

    if (availabilityArr.unavailable_unselectable_mask[0] !== "") {
        const unavailableArr: string[] = availabilityArr.unavailable_unselectable_mask[0].split(",");
        seatmap.status(unavailableArr, "unavailable");
    }
}

export function getSeatsKey(inSeatID: string, inPricescaleArr: I.SeatmapPricescale[]): string | undefined {
    for (let key in inPricescaleArr) {
        if (inPricescaleArr[key].mask[0].includes(inSeatID))
            return String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
    }

    return undefined;
}

export function splitSeatStr(inSeatStr: string): string[] {
    return inSeatStr.split(",").map((item) => item.trim());
}

export function createArrMatrix(inNumrows: number, inNumcols: number, inCharacter: string): string[][] {
    return Array(inNumrows).fill(null).map(() => Array(inNumcols).fill(inCharacter));
}

export function selectSeatsInCart(): void {
    const seatmap: any = config.state.seatmap;
    config.state.selectedSeatsArr.forEach(arr => {
        const seatID: string = arr[0];

        if (seatmap.get(seatID))
            seatmap.status(seatID, "selected");
    });
}

export function addSeatmap(inSelector: string, inMap: string[], inRowsNaming: string[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
    const containerSeatmap: any = (<any>window).jQuery(inSelector);

    // console.log(inSeatmapInitMap);
    // console.log(inSeats);
    // console.log(inLegend);

    config.state.seatmap = containerSeatmap.seatCharts({
        naming: {
            top: false,
            left: false,
            rows: inRowsNaming,
        },
        map: inMap,
        seats: inSeats,
        legend: inLegend,
        click: function () {
            return clickedSeat(this);
        }
    });
}

function createLegendItems(pricescaleArr: I.SeatmapPricescale[], venuePricescaleArr: I.Pricescale2[]): string[][] {
    return pricescaleArr.map((arr, index: number) => {
        const id: string = arr.id[0];
        const seatsKey: string = String.fromCharCode(97 + index).toLocaleUpperCase();
        const desc: string | undefined = venuePricescaleArr.find(obj => obj.id[0] === id)?.desc[0];
        const description: string = `${desc} €${pricescaleArr[index].ref_price[0]}`;
        return [seatsKey, "available", description];
    });
}

function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inPricescaleArr: I.SeatmapPricescale[], inAvailabilityArr: I.JSCAvailability): string[][] {
    const availableArr: string[] = inAvailabilityArr.available_selectable_mask[0].split(",");
    const unavailableArr: string[] = inAvailabilityArr.unavailable_unselectable_mask[0].split(",");

    inRows.forEach(element => {
        const row: I.LayoutRow2 = element;
        const Y: number = parseInt(row.y_cell_coord[0]) - 1;
        const seatsArr: string[] = row.seats[0].split("|");

        seatsArr.forEach(element => {
            const seatStr: string = element;
            // Form:
            // "568420,568420,15,7024,13 ,1"

            const seatArr: string[] = splitSeatStr(seatStr);
            // Form:
            // 0: "568528" -> ID
            // 1: "568528" -> ID
            // 2: "21" -> X-Coord benutzen
            // 3: "7024" -> section ID
            // 4: "13" -> Reihenbezeichnung
            // 5: "4" -> Platznummer

            // skip blacked out seats            
            if (!availableArr.includes(seatArr[0]) && !unavailableArr.includes(seatArr[0]))
                return;

            // const X: number = parseInt(seatArr[5]);
            const X: number = parseInt(seatArr[2]) - 1;
            const seatsKey: string | undefined = getSeatsKey(seatArr[0], inPricescaleArr);

            if (seatsKey)
                inArrMatrix[Y][X] = `${seatsKey}[${seatArr[0]}, ]`;


            // save seatArr in state with seatID as key
            config.state.layoutRows[seatArr[0]] = seatArr;
        });
    });

    return inArrMatrix;
}

function clickedSeat(inSeatmap: any) {
    if (inSeatmap.status() == 'available') {
        return clickAvailableSeat(inSeatmap);
    }
    else if (inSeatmap.status() === "selected") {
        return clickedSelectedSeat(inSeatmap);
    }
    else if (inSeatmap.status() == 'unavailable') {
        return "unavailable";
    }
    else {
        return inSeatmap.style();
    }
}

function clickAvailableSeat(inSeatmap: any) {
    const selectedSeat: I.JSCSelectedSeat = inSeatmap.settings;
    console.log(selectedSeat);

    if (State.maximumSelectedSeatsReached(selectedSeat))
        return "available";

    State.addSeatToState(selectedSeat);
    Cart.calcOverallPrice();
    CartButtons.setBtnCartText();

    return "selected";
}

function clickedSelectedSeat(inSeatmap: any) {
    const selectedSeat: I.JSCSelectedSeat = inSeatmap.settings;
    State.removeSeatFromState(selectedSeat);
    Cart.calcOverallPrice();
    CartButtons.setBtnCartText();

    return "available";
}