import { connect } from "react-redux";
import React from "react";
import MonacoEditor from "react-monaco-editor";
import { Card, Modal, Nav, NavItem, NavLink, TabContent, TabPane, Row, Col } from "reactstrap";
import { IoMdAdd, IoIosArrowForward } from "react-icons/io";
import StartTestModal from "../components/StartTestModal";
//import ScriptActions from "../actions/ScriptActions";
import TestActions from "../actions/TestActions";
import { AnyAction, bindActionCreators, Dispatch } from "redux";

const NEW_SCRIPT_NAME: string = "Untitled";
const NEW_SCRIPT_TEMPLATE: string = "export default function() {\n\n}\n";

interface State {
    activeTab: string;
    scripts: Map<string, string>;
    showRunModal: boolean;
}

class Editor extends React.Component<ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>, {}> {
    public readonly state: State;

    constructor(props: Readonly<any>) {
        super(props);

        this.onChange = this.onChange.bind(this);
        this.editorDidMount = this.editorDidMount.bind(this);
        this.onNewTab = this.onNewTab.bind(this);
        this.onRunTest = this.onRunTest.bind(this);
        this.onRunTestCancel = this.onRunTestCancel.bind(this);
        this.onRunTestConfirm = this.onRunTestConfirm.bind(this);

        const scripts: Map<string, string> = new Map();
        const defaultScript: string = `${NEW_SCRIPT_NAME} ${scripts.size + 1}`;
        scripts.set(defaultScript, NEW_SCRIPT_TEMPLATE);
        this.state = {
            activeTab: defaultScript,
            scripts,
            showRunModal: false,
        };
    }

    onChange(newValue: string, e: any) {
        const { scripts } = this.state;
        scripts.set(this.state.activeTab, newValue);
        this.setState({
            ...this.state,
            scripts,
        });
    }

    onClickTab(tab: string) {
        this.setState({
            ...this.state,
            activeTab: tab,
        });
    }

    onNewTab(e: any) {
        const { scripts } = this.state;
        const name: string = `${NEW_SCRIPT_NAME} ${scripts.size + 1}`;
        scripts.set(name, NEW_SCRIPT_TEMPLATE);
        this.setState({
            ...this.state,
            scripts,
        });
    }

    onRunTest(e: any) {
        e.preventDefault();
        this.setState({
            ...this.state,
            showRunModal: true,
        });
    }

    onRunTestConfirm(vus: number, duration: string) {
        const script: any = this.state.scripts.get(this.state.activeTab);
        if (script) {
            this.props.runTest(this.state.activeTab, script, vus, duration);
        }
    }

    onRunTestCancel() {
        this.setState({
            ...this.state,
            showRunModal: false,
        });
    }

    editorDidMount(editor: any, monaco: any) {
        editor.focus();
    }

    render() {
        const options: any = {
            lineNumbers: "on",
            selectOnLineNumbers: true,
            tabCompletion: true,
        };

        const navItems: Array<any> = [];
        const tabs: Array<any> = [];
        this.state.scripts.forEach((value, key) => {
            navItems.push(
                <NavItem>
                    <NavLink onClick={() => this.onClickTab(key)}>{key}</NavLink>
                </NavItem>
            );
            tabs.push(
                <TabPane tabId={key}>
                    <Row>
                        <Col>
                            <Card body>
                                <MonacoEditor
                                    width="95vw"
                                    height="80vh"
                                    language="javascript"
                                    theme="vs-dark"
                                    options={options}
                                    onChange={this.onChange}
                                    editorDidMount={this.editorDidMount}
                                    value={value}
                                />
                            </Card>
                        </Col>
                    </Row>
                </TabPane>
            );
        });

        return (
            <div>
                <Modal isOpen={this.state.showRunModal}>
                    <StartTestModal onCancel={this.onRunTestCancel} onConfirm={this.onRunTestConfirm} />
                </Modal>
                <Nav tabs>
                    {navItems}
                    <NavItem>
                        <NavLink onClick={this.onNewTab}>
                            <IoMdAdd />
                        </NavLink>
                    </NavItem>
                    <NavLink onClick={this.onRunTest}>
                        <IoIosArrowForward className="navbar-runtest" />
                    </NavLink>
                </Nav>
                <TabContent activeTab={this.state.activeTab}>{tabs}</TabContent>
            </div>
        );
    }
}

const mapStateToProps = (state: any) => {
    const { scriptState, testState } = state;

    return {
        scriptState,
        testState,
    };
};

const mapDispatchToProps = (dispatch: Dispatch<AnyAction>) =>
    bindActionCreators(
        {
            ...TestActions,
        },
        dispatch
    );

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Editor);
