import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt, StrListCast } from '../../../fields/Doc';
import { NumCast, StrCast } from '../../../fields/Types';
import { Docs } from '../../documents/Documents';
import { FieldsDropdown } from '../FieldsDropdown';
import { PinDocView } from '../PinFuncs';
import { DocumentView } from '../nodes/DocumentView';
import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import './CollectionTimeView.scss';
import { computeTimelineLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';

@observer
export class CollectionTimeView extends CollectionSubView() {
    @observable _collapsed: boolean = false;
    @observable _focusPivotField: Opt<string> = undefined;

    constructor(props: SubCollectionViewProps) {
        super(props);
        makeObservable(this);
    }

    componentDidMount() {
        this._props.setContentViewBox?.(this);
    }

    get pivotField() {
        return this._focusPivotField || StrCast(this.layoutDoc._pivotField);
    }

    getAnchor = (addAsAnnotation: boolean) => {
        const anchor = Docs.Create.ConfigDocument({
            annotationOn: this.Document,
        });
        PinDocView(anchor, { pinData: { collectionType: true, pivot: true, filters: true } }, this.Document);
        addAsAnnotation && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_annotations', anchor); // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered
        return anchor;
    };

    @action
    scrollPreview = (docView: DocumentView, anchor: Doc /* , focusSpeed: number, options: FocusViewOptions */) => {
        // if in preview, then override document's fields with view spec
        this._focusFilters = StrListCast(anchor.config_docFilters);
        this._focusRangeFilters = StrListCast(anchor.config_docRangeFilters);
        this._focusPivotField = StrCast(anchor.config_pivotField);
        return undefined;
    };

    toggleVisibility = action(() => {
        this._collapsed = !this._collapsed;
    });

    onMinDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(
            this,
            e,
            action((moveEv: PointerEvent, down: number[], delta: number[]) => {
                const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
                const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
                this.Document[this._props.fieldKey + '-timelineMinReq'] = minReq + ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
                this.Document[this._props.fieldKey + '-timelineSpan'] = undefined;
                return false;
            }),
            returnFalse,
            emptyFunction
        );
    };

    onMaxDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(
            this,
            e,
            action((moveEv, down: number[], delta: number[]) => {
                const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
                const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
                this.Document[this._props.fieldKey + '-timelineMaxReq'] = maxReq + ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
                return false;
            }),
            returnFalse,
            emptyFunction
        );
    };

    onMidDown = (e: React.PointerEvent) => {
        setupMoveUpEvents(
            this,
            e,
            action((moveEv: PointerEvent, down: number[], delta: number[]) => {
                const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
                const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
                this.Document[this._props.fieldKey + '-timelineMinReq'] = minReq - ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
                this.Document[this._props.fieldKey + '-timelineMaxReq'] = maxReq - ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
                return false;
            }),
            returnFalse,
            emptyFunction
        );
    };

    layoutEngine = () => computeTimelineLayout.name;
    @computed get contents() {
        return (
            <div className="collectionTimeView-innards" key="timeline" style={{ pointerEvents: this._props.isContentActive() ? undefined : 'none' }}>
                <CollectionFreeFormView
                    {...this._props}
                    engineProps={{ pivotField: this.pivotField, childFilters: this.childDocFilters, childFiltersByRanges: this.childDocRangeFilters }}
                    fitContentsToBox={returnTrue}
                    layoutEngine={this.layoutEngine}
                />
            </div>
        );
    }

    render() {
        return (
            <div className="collectionTimeView" style={{ width: this._props.PanelWidth(), height: '100%' }}>
                {this.contents}
                <div style={{ right: 0, top: 0, position: 'absolute' }}>
                    <FieldsDropdown
                        Document={this.Document}
                        selectFunc={fieldKey => {
                            this.layoutDoc._pivotField = fieldKey;
                        }}
                        placeholder={StrCast(this.layoutDoc._pivotField)}
                    />
                </div>
                {!this._props.isSelected() ? null : (
                    <>
                        <div className="collectionTimeView-thumb-min collectionTimeView-thumb" key="min" onPointerDown={this.onMinDown} />
                        <div className="collectionTimeView-thumb-max collectionTimeView-thumb" key="mid" onPointerDown={this.onMaxDown} />
                        <div className="collectionTimeView-thumb-mid collectionTimeView-thumb" key="max" onPointerDown={this.onMidDown} />
                    </>
                )}
            </div>
        );
    }
}
