import React from "react";
import PropTypes from "prop-types";
import classNames from "classnames";

const LAYER_HEADER_WIDTH = 210;

import IDUtil from "../../../../util/IDUtil";

import Section from "./Section";

// Render the given layers with a slight delay, so the UI has time to process the mouse interaction
class Layer extends React.Component {
    constructor(props) {
        super(props);

        this.doubleClickTime = this.props.doubleClickTime
            ? this.props.doubleClickTime
            : 200;
        this.doubleClickOffset = this.props.doubleClickOffset
            ? this.props.doubleClickOffset
            : 5;
    }

    onMouseDown = (e) => {
        const leftMouseButton = e.button === 0;
        const time = new Date().getTime();

        const clickPosition =
            this.props.start +
            (e.pageX - LAYER_HEADER_WIDTH) / this.props.pixelsPerSecond;

        // check for double click and if available call layer.onDoubleClick
        if (
            leftMouseButton &&
            this.interactionVars &&
            this.props.layer.onDoubleClick &&
            time - this.interactionVars.lastDown < this.doubleClickTime &&
            e.pageX - this.interactionVars.downX < this.doubleClickOffset
        ) {
            this.interactionVars = null;
            e.stopPropagation();

            // pass to onDoubleClick
            e.persist();
            this.props.layer.onDoubleClick(clickPosition, e);
        } else {
            // set interaction variables
            this.interactionVars = {
                downX: e.pageX,
                lastDown: leftMouseButton ? time : 0,
            };

            // make layer active
            this.props.onSectionClick(this.props.layer.id, "");

            // optional onMouseDown callback
            this.props.layer.onClick &&
                this.props.layer.onClick(clickPosition, e.originalEvent);
        }
    };

    onSectionClick = (layerId, sectionId) => {
        this.props.onSectionClick(layerId, sectionId);
    };

    render() {
        const {
            layer,
            start,
            end,
            pixelsPerSecond,
            activeLayerId,
            activeSectionId,
        } = this.props;

        // Get layers with sections in view
        const durationPadding = (end - start) * 0.03;
        return (
            <div
                className={classNames(
                    IDUtil.cssClassName("tl-layer"),
                    layer.className
                )}
                style={{
                    height: layer.height,
                }}
                onMouseDown={this.onMouseDown}
                layer={layer.id}
            >
                {layer.sections
                    .filter(
                        (section) =>
                            section.start >
                                start -
                                    (section.end - section.start) -
                                    durationPadding &&
                            section.end <
                                end +
                                    (section.end - section.start) +
                                    durationPadding
                    )
                    .map((section) => (
                        <Section
                            key={section.id}
                            sectionId={section.id}
                            layerId={layer.id}
                            start={section.start}
                            active={
                                layer.id === activeLayerId &&
                                section.id === activeSectionId
                            }
                            cropped={section.start < start}
                            highlight={section.highlight}
                            match={section.match}
                            left={Math.round(
                                section.start >= start
                                    ? section.start * pixelsPerSecond
                                    : start * pixelsPerSecond
                            )}
                            width={
                                Math.round(
                                    section.start >= start
                                        ? Math.max(
                                              0.25, // always keep a minimum duration in view so the section could still be edited
                                              section.end - section.start
                                          ) * pixelsPerSecond
                                        : (Math.max(
                                              0.25, // always keep a minimum duration in view so the section could still be edited
                                              section.end - section.start
                                          ) +
                                              Math.min(
                                                  0,
                                                  section.start - start
                                              )) *
                                              pixelsPerSecond
                                ) + 1 // +1 for filling gaps
                            }
                            onClick={this.onSectionClick}
                        >
                            {section.data}
                        </Section>
                    ))}
            </div>
        );
    }
}

export const LayerPropTypes = PropTypes.shape({
    id: PropTypes.number.isRequired,
    title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
    description: PropTypes.string,
    sections: PropTypes.arrayOf(
        PropTypes.shape({
            id: PropTypes.string.isRequired,
            start: PropTypes.number.isRequired,
            end: PropTypes.number.isRequired,
            rawData: PropTypes.string,
            data: PropTypes.object.isRequired,
        }).isRequired
    ).isRequired,
    onClick: PropTypes.func, // on layer click
    onDoubleClick: PropTypes.func, // on layer double click
    headerChildren: PropTypes.object, // additional children to render in layer header
}).isRequired;

Layer.propTypes = {
    start: PropTypes.number.isRequired,
    end: PropTypes.number.isRequired,
    pixelsPerSecond: PropTypes.number.isRequired,
    layer: LayerPropTypes,
    activeLayerId: PropTypes.number,
    activeSectionId: PropTypes.string,
    onSectionClick: PropTypes.func,
    doubleClickTime: PropTypes.number,
    doubleClickOffset: PropTypes.number,
};

export default Layer;
