import React, { createRef, useEffect, useState } from "react";
import PropTypes from "prop-types";
import ReactCSSTransitionGroup from "react-addons-css-transition-group";

import {
    NgIf, Icon, EventEmitter, Dropdown, DropdownButton, DropdownList,
    DropdownItem, Container, Loader,
} from "../../components/";
import { debounce, alert, confirm, prompt, notify } from "../../helpers/";
import { Files } from "../../model/";
import { t } from "../../locales/";
import "./submenu.scss";
class SubmenuComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            search_input_visible: false,
            search_keyword: "",
        };
        this.$input = createRef();

        this.onSearchChange_Backpressure = debounce(this.onSearchChange, 400);
        this._onKeyPress = (e) => {
            if (e.keyCode === 27) { // escape key
                this.setState({
                    search_keyword: "",
                    search_input_visible: false,
                });
                if (this.$input.current) this.$input.current.blur();
                this.props.onSearch(null);
            } else if (e.ctrlKey && e.keyCode === 70) { // 'Ctrl F' shortcut to search
                e.preventDefault();
                this.setState({
                    search_input_visible: true,
                });
                if (this.$input.current) this.$input.current.focus();
            } else if (e.altKey && (e.keyCode === 49 || e.keyCode === 50)) { // 'alt 1' 'alt 2' shortcut
                e.preventDefault();
                this.onViewChange();
            }
        };
    }

    componentDidMount() {
        window.addEventListener("keydown", this._onKeyPress);
    }
    componentWillUnmount() {
        window.removeEventListener("keydown", this._onKeyPress);
    }

    onNew(type) {
        this.props.emit("new::"+type);
    }
    onDelete(arrayOfPaths) {
        prompt.now(
            t("Confirm by typing") + " \"remove\"",
            (answer) => {
                if (answer !== "remove") {
                    return Promise.resolve();
                }
                this.props.emit("file.delete.multiple", arrayOfPaths);
                return Promise.resolve();
            },
            () => {/* click on cancel */},
        );
    }
    onDownload(arrayOfPaths) {
        this.props.emit("file.download.multiple", arrayOfPaths);
    }

    onExtract(arrayOfPaths) {
        alert.now(<ExtractZipRequest
                      refresh={this.props.emit.bind(this, "file.refresh")}
                      paths={arrayOfPaths} />);
    }

    onViewChange() {
        requestAnimationFrame(() => this.props.onViewUpdate());
    }

    onSortChange(e) {
        this.props.onSortUpdate(e);
    }

    onSearchChange(search, e) {
        this.props.onSearch(search.trim());
    }

    onSearchToggle() {
        if (new Date() - this.search_last_toggle < 200) {
            // avoid bluring event cancelling out the toogle
            return;
        }
        if (this.$input.current) this.$input.current.focus();
        this.setState({
            search_input_visible: !this.state.search_input_visible,
        }, () => {
            if (this.state.search_input_visible == false) {
                this.props.onSearch(null);
                this.setState({ search_keyword: "" });
            }
        });
    }

    closeIfEmpty() {
        if (this.state.search_keyword.trim().length > 0) return;
        this.search_last_toggle = new Date();
        this.setState({
            search_input_visible: false,
            search_keyword: "",
        });
        this.props.onSearch(null);
    }

    onSearchKeypress(s, backpressure = true, e) {
        if (backpressure) {
            this.onSearchChange_Backpressure(s);
        } else {
            this.onSearchChange(s);
        }
        this.setState({ search_keyword: s });

        if (e && e.preventDefault) {
            e.preventDefault();
        }
    }

    render() {
        return (
            <div className={"component_submenu" + (this.props.selected.length > 0 || this.state.search_input_visible ? " sticky" : "")}>
                <Container>
                    <div className={"menubar no-select"+(this.state.search_input_visible ? " search_focus" : "")}>
                        <NgIf
                            className="button-new-file"
                            cond={this.props.accessRight.can_create_file !== false && this.props.selected.length === 0}
                            onClick={this.onNew.bind(this, "file")}
                            type="inline">
                            { window.innerWidth < 410 && t("New File").length > 10 ? t("New File", null, "NEW_FILE::SHORT") : t("New File") }
                        </NgIf>
                        <NgIf
                            className="button-new-folder"
                            cond={this.props.accessRight.can_create_directory !== false && this.props.selected.length === 0}
                            onClick={this.onNew.bind(this, "directory")}
                            type="inline">
                            { window.innerWidth < 410 && t("New Folder").length > 10 ? t("New Folder", null, "NEW_FOLDER::SHORT") : t("New Folder") }
                        </NgIf>
                        <NgIf
                            className="button-download"
                            cond={this.props.selected.length > 0}
                            type="inline"
                            onMouseDown={this.onDownload.bind(this, this.props.selected)}>
                            <ReactCSSTransitionGroup transitionName="submenuwithSelection" transitionLeave={false} transitionEnter={false} transitionAppear={true} transitionAppearTimeout={10000}>
                                <span>{ t("Download") }</span>
                            </ReactCSSTransitionGroup>
                        </NgIf>
                        <NgIf
                            className="button-remove"
                            cond={this.props.selected.length > 0 && this.props.accessRight.can_delete !== false}
                            type="inline"
                            onMouseDown={this.onDelete.bind(this, this.props.selected)}>
                            <ReactCSSTransitionGroup transitionName="submenuwithSelection" transitionLeave={false} transitionEnter={false} transitionAppear={true} transitionAppearTimeout={10000}>
                                <span>{ t("Remove") }</span>
                            </ReactCSSTransitionGroup>
                        </NgIf>
                        <NgIf
                            className="button-extract"
                            cond={/canary/.test(location.search) && this.props.selected.length === 1 && this.props.selected[0].replace(/.*\.([^\.]+)/, "$1") === "zip"}
                            type="inline"
                            onMouseDown={this.onExtract.bind(this, this.props.selected)}>
                            <ReactCSSTransitionGroup transitionName="submenuwithSelection" transitionLeave={false} transitionEnter={false} transitionAppear={true} transitionAppearTimeout={10000}>
                                <span>{ t("Extract") }</span>
                            </ReactCSSTransitionGroup>
                        </NgIf>

                        {
                            this.props.selected.length === 0 && (
                                <React.Fragment>
                                    <Dropdown
                                        className="view sort"
                                        onChange={this.onSortChange.bind(this)}>
                                        <DropdownButton>
                                            <Icon name="sort"/>
                                        </DropdownButton>
                                        <DropdownList>
                                            <DropdownItem
                                                name="type"
                                                icon={this.props.sort === "type" ? "check" : null}>
                                                { t("Sort By Type") }
                                            </DropdownItem>
                                            <DropdownItem
                                                name="date"
                                                icon={this.props.sort === "date" ? "check" : null}>
                                                { t("Sort By Date") }
                                            </DropdownItem>
                                            <DropdownItem
                                                name="name"
                                                icon={this.props.sort === "name" ? "check" : null}>
                                                { t("Sort By Name") }
                                            </DropdownItem>
                                        </DropdownList>
                                    </Dropdown>
                                    <div
                                        className="view list-grid"
                                        onClick={this.onViewChange.bind(this)}>
                                        <Icon name={this.props.view === "grid" ? "list" : "grid"}/>
                                    </div>
                                    <div className="view">
                                        <form onSubmit={(e) => this.onSearchKeypress(this.state.search_keyword, false, e)}>
                                            <label className="view search" onClick={this.onSearchToggle.bind(this, null)}>
                                                <NgIf cond={this.state.search_input_visible !== true}>
                                                    <Icon name="search_dark"/>
                                                </NgIf>
                                                <NgIf cond={this.state.search_input_visible === true}>
                                                    <Icon name="close_dark"/>
                                                </NgIf>
                                            </label>
                                            <NgIf cond={this.state.search_input_visible !== null} type="inline">
                                                <input
                                                    ref={this.$input}
                                                    onBlur={this.closeIfEmpty.bind(this, false)}
                                                    style={{ "width": this.state.search_input_visible ? "180px" : "0px" }}
                                                    value={this.state.search_keyword}
                                                    onChange={(e) => this.onSearchKeypress(e.target.value, true)}
                                                    type="text"
                                                    id="search"
                                                    placeholder={ t("search") }
                                                    name="search"
                                                    autoComplete="off" />
                                                <label htmlFor="search" className="hidden">{ t("search") }</label>
                                            </NgIf>
                                        </form>
                                    </div>
                                </React.Fragment>
                            )
                        }
                    </div>
                </Container>
            </div>
        );
    };
}

SubmenuComponent.propTypes = {
    accessRight: PropTypes.object,
    onSortUpdate: PropTypes.func.isRequired,
    sort: PropTypes.string.isRequired,
};


function ExtractZipRequest({ paths, refresh }) {
    const [error, setError] = useState(null);
    useEffect(() => {
        const controller = new AbortController();
        Files.unzip(paths, controller.signal)
            .then((a) => {
                refresh();
                document.querySelector("#modal-box").click();
            })
            .catch((err) => {
                refresh();
                setError(t(err && err.message))
            });
        return () => controller.abort();
    }, []);
    return (
        <div>
            {
                error === null ? (
                    <React.Fragment>
                        <style>{`
                           .component_modal button { opacity: 0 }
                           .component_modal .component_loader { margin: 30px 0 0 0; }
                        `}</style>
                        <Loader />
                    </React.Fragment>
                ) : (
                    <div>{ error }</div>
                )
            }
        </div>
    )
}

export const Submenu = EventEmitter(SubmenuComponent);
