import React, {Component} from "react";
import {
    Button,
    Chip,
    FormControl,
    FormControlLabel,
    FormGroup,
    FormLabel,
    Grid,
    Snackbar,
    Switch,
    TextField,
    Typography
} from "@mui/material";
import RestartAltIcon from '@mui/icons-material/RestartAlt';
import CloseIcon from '@mui/icons-material/Close';
import SaveIcon from '@mui/icons-material/Save';
import {PAGE} from "./App";
import {
    Config,
    GameInput,
    GameRules,
    GameSwitch,
    GameSwitchNames,
    IPCListenChannels,
    NFCCard,
    NFCCardType,
    NFCPropertyCard,
    PropertyColor
} from "../RawConstants";
import NfcIcon from "@mui/icons-material/Nfc";
import IPCRendererListener from "./IPCRendererListener";
import CardSetup from "./CardSetup";


interface InitialSetupState {
    open: boolean,
    switchValues: GameSwitch[],
    inputValues: GameInput[],
    savedMsg: boolean,
    openNFCModal: boolean,
    nfcCard: NFCCard,
    validCard: boolean
}

const defaultConf: InitialSetupState = {
    open: true,
    savedMsg: false,
    openNFCModal: false,
    nfcCard: null,
    validCard: false,
    switchValues: [
        {
            name: "GET_BONUS_PASSING_START",
            label: "Über Los Bonus einziehen",
            value: true
        },
        {
            name: "DOUBLE_BONUS_ON_GO",
            label: "Wenn auf Los, doppelten Bonus einziehen",
            depends: "GET_BONUS_PASSING_START",
            value: true
        },
        {
            name: "PUT_PAID_PENALTIES_IN_MIDDLE",
            label: "Gezahlte Strafen in die 'Mitte' legen",
            value: true
        },
        {
            name: "RECEIVE_PENALTIES_AT_FREE_PARKING",
            label: "Bei 'Frei Parken' Strafen aus der 'Mitte' einziehen",
            depends: "PUT_PAID_PENALTIES_IN_MIDDLE",
            value: true
        },
        {
            name: "PUT_10_IN_MIDDLE_AFTER_EACH_GO",
            label: "Nach jedem Los 10 in die Mitte",
            depends: "PUT_PAID_PENALTIES_IN_MIDDLE",
            value: false
        },
        {
            name: "STREET_MUST_BE_AUCTIONED_IF_NOT_PURCHASED",
            label: "Straße muss versteigert werden bei Nichtkauf",
            value: true
        },
        {
            name: "TWO_HOTELS_PER_STREET_ALLOWED",
            label: "Zwei Hotels pro Straße erlaubt",
            value: false
        },
        {
            name: "MORTGAGE_REDUCES_RENT",
            label: "Hypothek verringert Miete",
            value: false
        },
        {
            name: "GOODS_GO_TO_OTHER_PLAYERS_UPON_BANKRUPTCY",
            label: "Güter gehen an anderen Spieler über bei Bankrott",
            value: true
        },
        {
            name: "STREETS_CAN_BE_SOLD_BACK_TO_THE_BANK",
            label: "Straßen können zurück an die Bank verkauft werden",
            value: true
        },
        {
            name: "PRISON_CAN_BE_PURCHASED_RENT_GOES_TO_PLAYER",
            label: "Gefängnis kann erworben werden, Miete geht an den Spieler",
            value: false
        },
        {
            name: "KEEP_MONEY_MORE_SECRET",
            label: "Geld von anderen Spielern ungenauer anzeigen",
            value: false
        }

    ],
    inputValues: [
        {
            name: "STARTING_CASH",
            type: "number",
            label: "Start Guthaben",
            value: "1500"
        },
        {
            name: "PASSING_GO_CASH",
            type: "number",
            label: "Lohn über Los",
            value: "200"
        },
        {
            name: "PRISON_RELEASE_FEE",
            type: "number",
            label: "Gefängnis Gebühren",
            value: "50"
        },
        {
            name: "CURRENCY",
            type: "text",
            label: "Währung",
            value: "€"
        }
    ]
}


export default class Setup extends Component<{}, InitialSetupState> {
    constructor(props: {}) {
        super(props);
        let x: NFCPropertyCard = {
            cardType: NFCCardType.PROPERTY,
            "name": "Test",
            mortgageValue: 2,
            rent: 100,
            buyValue: 200,
            specialProperties: "",
            color: PropertyColor.BEIGE,
            fullSetAmount: 2,

        }

        this.state = {
            ...defaultConf,

        }

    }

    reset = () => {
        this.setState(prevState => ({
            ...prevState,
            ...defaultConf
        }))

        //window.api.request("")
    }

    style = {
        position: 'absolute',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        width: '50%',
        bgcolor: 'background.paper',
        border: '2px solid #000',
        boxShadow: 24,
        p: 4,
    };

    onSwitch = (event: React.ChangeEvent<HTMLInputElement>) => {
        const {name, checked} = event.target;

        this.setState((prevState) => ({
            ...prevState,
            switchValues: prevState.switchValues.map((switchObj) => {
                if (switchObj.name === name) {
                    return {
                        ...switchObj,
                        value: checked
                    };
                }
                return switchObj;
            })
        }));
    }

    onInput = (event: React.ChangeEvent<HTMLInputElement>) => {
        const {name, value} = event.target;

        this.setState((prevState) => ({
            ...prevState,
            inputValues: prevState.inputValues.map((switchObj) => {
                if (switchObj.name === name) {
                    return {
                        ...switchObj,
                        value: value
                    };
                }
                return switchObj;
            })
        }));
    }

    getSettings = () => {
        return new Promise<void>((resolve, reject) => {
            window.api.request("SETTINGS", {}).then(answer => {
                try {
                    let data = answer.data as Config;
                    for (let [sw, state] of Object.entries(data.rules.switchValues)) {
                        this.setState((prevState) => ({
                            ...prevState,
                            switchValues: prevState.switchValues.map((obj) => {
                                if (obj.name === sw) {
                                    return {
                                        ...obj,
                                        value: state
                                    };
                                }
                                return obj;
                            })
                        }));
                    }
                    for (let [sw, state] of Object.entries(data.rules.inputValues)) {
                        this.setState((prevState) => ({
                            ...prevState,
                            inputValues: prevState.inputValues.map((obj) => {
                                if (obj.name === sw) {
                                    return {
                                        ...obj,
                                        value: state
                                    };
                                }
                                return obj;
                            })
                        }));
                    }
                    resolve();
                } catch (e) {
                    reject(e);
                }
            })
        })

    }

    saveSettings = (silent = false) => {
        let gameSettings: any = {
            switchValues: {},
            inputValues: {}
        };


        for (let ele of this.state.switchValues) {
            gameSettings.switchValues[ele.name] = ele.value;
            if (!!ele.depends && ele.value)
                gameSettings.switchValues[ele.name] = this.checkDependsValue(ele.depends);
        }

        for (let ele of this.state.inputValues) {
            gameSettings.inputValues[ele.name] = ele.value;
        }

        window.api.request("SETTINGS", {data: {rules: gameSettings as GameRules}}).then();

        if (!silent)
            this.setState(prevState => ({
                ...prevState,
                savedMsg: true
            }));
    }


    onNFCRawEvent = (card: NFCCard|null, isComplete: boolean) => {
        this.setState(prevState => ({
            ...prevState,
            openNFCModal: true,
            nfcCard: card,
            validCard: isComplete
        }));
        console.log(card);
    }

    private rawNFCListener: number = 0;

    componentDidMount() {

        this.rawNFCListener = IPCRendererListener.attach(IPCListenChannels.NFC_RAW, (message) => {
            this.onNFCRawEvent(message.data, message.status);
            console.log("Got an raw nfc event")
        })
        this.getSettings().then();
    }

    componentWillUnmount() {
        IPCRendererListener.detach(this.rawNFCListener);
    }

    handleClose = () => {
        window.app.toggleWiFiSettings(false);
    }

    checkDependsValue = (depends: GameSwitchNames) => {
        for (let x of this.state.switchValues) {
            if (x.name == depends)
                return x.value;
        }
    }

    render() {
        return <div className="setup">
            <Snackbar
                open={this.state.savedMsg}
                autoHideDuration={6000}
                onClose={() => {
                    this.setState(prevState => ({
                        ...prevState,
                        savedMsg: false
                    }))
                }}
                message={"Einstellungen gespeichert!"}
            />


            {this.state.openNFCModal &&
            <CardSetup card={this.state.nfcCard} validCard={this.state.validCard} closeCallback={() => this.setState(prevState => ({
                ...prevState,
                openNFCModal: false
            }))}/>}
            <Typography variant="h2" sx={{mb: 2}}>Einstellungen</Typography>
            <Grid container spacing={3}>
                <Grid item xs={6}>
                    <FormControl component="fieldset" variant="standard">
                        <FormLabel component="legend">Schalter-Regeln</FormLabel>
                        <FormGroup>
                            {Object.values(this.state.switchValues).map(value => {
                                return (
                                    <FormControlLabel key={value.name} sx={{mb: 1}}
                                                      control={
                                                          <Switch
                                                              checked={(value.value && !value.depends) || (value.value && !!value.depends && this.checkDependsValue(value.depends))}
                                                              disabled={!!value.depends && !this.checkDependsValue(value.depends)}
                                                              onChange={this.onSwitch}
                                                              name={value.name}/>
                                                      } label={value.label}
                                    />)
                            })}
                        </FormGroup>
                    </FormControl>
                </Grid>
                <Grid item xs={6}>
                    <FormControl component="fieldset" variant="standard">
                        <FormLabel component="legend">Werte-Regeln</FormLabel>
                        <FormGroup>
                            {Object.values(this.state.inputValues).map(value => {
                                return (
                                    <FormControlLabel key={value.name} sx={{mb: 2}}
                                                      control={
                                                          <TextField type={value.type} variant="standard"
                                                                     value={value.value}
                                                                     disabled={!!value.depends && !this.checkDependsValue(value.depends)}
                                                                     onChange={this.onInput}
                                                                     name={value.name}/>
                                                      } label={value.label}
                                    />)
                            })}
                        </FormGroup>
                    </FormControl>
                    <FormControl sx={{mt: 5, mb: 1}} component="fieldset" variant="standard">
                        <FormLabel component="legend">Spielkarten</FormLabel>
                        <Typography sx={{ml: -2}} width={"95%"} variant="body1"><Chip
                            label={<div><NfcIcon sx={{marginTop: 0.9}} className={"animationBreathe"}
                                                 color="primary"/> NFC</div>} color="secondary"
                            variant="outlined"/><br/>Bitte die Karte an das Lesegerät halten, um sie zu
                            konfigurieren.<br/>Anschließend können die Einstellungen der Karte im Dialog angepasst
                            werden.</Typography>
                    </FormControl>
                </Grid>
                <Grid item xs={3.5}></Grid>
                <Grid item xs={"auto"} alignItems="center">
                    <Button variant="contained" color="secondary" onClick={() => {
                        this.getSettings().then(r => window.app.setPage(PAGE.STARTUP));
                    }}>Abbrechen <CloseIcon/></Button>
                    <Button sx={{ml: 2}} variant="outlined" color="error"
                            onClick={() => this.reset()}>Zurücksetzen <RestartAltIcon/></Button>
                    <Button sx={{ml: 2}} variant="contained" color="success" onClick={() => {
                        this.saveSettings();
                        window.app.setPage(PAGE.STARTUP);
                    }}>Speichern <SaveIcon/></Button>
                </Grid>
            </Grid>


        </div>
    }

}