import * as classNames from "classnames";
import { observer } from "mobx-react";
import * as React from "react";
import { Button, Icon, Progress, Segment } from "semantic-ui-react";

import { Duration } from "@common/Duration";
import log from "@common/logger";
import { Section, SectionRun, SectionRunner } from "@common/sprinklersRpc";

interface PausedStateProps {
    paused: boolean;
    togglePaused: () => void;
}

function PausedState({ paused, togglePaused }: PausedStateProps) {
    const classes = classNames({
        "sectionRunner--pausedState": true,
        "sectionRunner--pausedState-paused": paused,
        "sectionRunner--pausedState-unpaused": !paused,
    });
    return (
        <Button className={classes} size="tiny" onClick={togglePaused}>
            <Icon name={paused ? "pause" : "play"}/>
            {paused ? "Paused" : "Processing"}
        </Button>
    );
}

class SectionRunView extends React.Component<{
    run: SectionRun;
    sections: Section[];
}, {
    now: number;
}> {
    animationFrameHandle: number | null = null;
    startTime: number;

    constructor(p: any) {
        super(p);
        const now = performance.now();
        this.state = { now };
        this.startTime = Date.now() - now;
    }

    componentDidMount() {
        this.requestAnimationFrame();
    }

    componentDidUpdate() {
        this.requestAnimationFrame();
    }

    componentWillUnmount() {
        this.cancelAnimationFrame();
    }

    cancelAnimationFrame = () => {
        if (this.animationFrameHandle != null) {
            cancelAnimationFrame(this.animationFrameHandle);
            this.animationFrameHandle = null;
        }
    }

    requestAnimationFrame = () => {
        const startTime = this.props.run.startTime;
        if (startTime != null) {
            if (this.animationFrameHandle == null) {
                this.animationFrameHandle = requestAnimationFrame(this.updateNow);
            }
        } else {
            this.cancelAnimationFrame();
        }
    }

    updateNow = (now: number) => {
        this.animationFrameHandle = null;
        this.setState({
            now: this.startTime + now,
        });
        this.requestAnimationFrame();
    }

    render() {
        const { run, sections } = this.props;
        const startTime = run.unpauseTime ? run.unpauseTime : run.startTime;
        const now = this.state.now;
        const section = sections[run.section];
        const duration = Duration.fromSeconds(run.duration);
        const cancel = run.cancel;
        let running: boolean = false; // tslint:disable-line:no-unused-variable
        let paused: boolean = false;
        let progressBar: React.ReactNode | undefined;
        if (startTime != null) {
            let elapsed = (run.totalDuration - run.duration);
            if (run.pauseTime) {
                paused = true;
            } else {
                running = true;
                elapsed += (now - startTime.valueOf()) / 1000;
            }
            const percentage = elapsed / run.totalDuration;
            progressBar =
                <Progress color={paused ? "yellow" : "blue"} size="tiny" percent={percentage * 100}/>;
        }
        const description = `'${section.name}' for ${duration.toString()}` +
            (paused ? " (paused)" : "") +
            (running ? " (running)" : "");
        return (
            <Segment className="sectionRun">
                <div className="flex-horizontal-space-between">
                    {description}
                    <Button negative onClick={cancel} icon size="mini"><Icon name="remove"/></Button>
                </div>
                {progressBar}
            </Segment>
        );
    }
}

@observer
export default class SectionRunnerView extends React.Component<{
    sectionRunner: SectionRunner, sections: Section[],
}, {}> {
    render() {
        const { current, queue, paused } = this.props.sectionRunner;
        const { sections } = this.props;
        const queueView = queue.map((run) =>
            <SectionRunView key={run.id} run={run} sections={sections}/>);
        if (current) {
            queueView.unshift(<SectionRunView key={-1} run={current} sections={sections}/>);
        }
        if (queueView.length === 0) {
            queueView.push(<Segment key={0}>No items in queue</Segment>);
        }
        return (
            <Segment className="sectionRunner">
                <div style={{ display: "flex", alignContent: "baseline" }}>
                    <h4 style={{ marginBottom: 0 }}>Section Runner Queue</h4>
                    <div className="flex-spacer"/>
                    <PausedState paused={paused} togglePaused={this.togglePaused}/>
                </div>
                <Segment.Group className="queue">
                    {queueView}
                </Segment.Group>
            </Segment>
        );
    }

    togglePaused = () => {
        const { sectionRunner } = this.props;
        const paused = !sectionRunner.paused;
        sectionRunner.setPaused(paused)
            .then((res) => log.info(res, "set section runner paused to " + paused))
            .catch((err) => log.info({ err }, "error setting section runner paused status"));
    }
}
