import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { VideoField } from '../../../../fields/URLField';
import { Upload } from '../../../../server/SharedMediaTypes';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { FieldView, FieldViewProps } from '../FieldView';
import { VideoBox } from '../VideoBox';
import { RecordingView } from './RecordingView';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Presentation } from '../../../util/TrackMovements';
import { Doc } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { BoolCast, DocCast } from '../../../../fields/Types';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { DocumentManager } from '../../../util/DocumentManager';
import { Docs } from '../../../documents/Documents';

@observer
export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
    public static LayoutString(fieldKey: string) {
        return FieldView.LayoutString(RecordingBox, fieldKey);
    }

    private _ref: React.RefObject<HTMLDivElement> = React.createRef();

    componentDidMount() {
        this.props.setContentView?.(this);
        Doc.SetNativeWidth(this.dataDoc, 1280);
        Doc.SetNativeHeight(this.dataDoc, 720);
    }

    @observable result: Upload.AccessPathInfo | undefined = undefined;
    @observable videoDuration: number | undefined = undefined;

    @action
    setVideoDuration = (duration: number) => {
        this.videoDuration = duration;
    };

    @action
    setResult = (info: Upload.AccessPathInfo, presentation?: Presentation) => {
        this.result = info;
        this.dataDoc.type = DocumentType.VID;
        this.dataDoc[this.fieldKey + '_duration'] = this.videoDuration;

        this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
        this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client);
        this.dataDoc[this.fieldKey + '_recorded'] = true;
        // stringify the presentation and store it
        if (presentation?.movements) {
            const presCopy = { ...presentation };
            presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: movement.doc[Id] })) as any;
            this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy);
        }
    };

    Record: undefined | (() => void);
    Pause: undefined | (() => void);
    Finish: undefined | (() => void);
    getControls = (record: () => void, pause: () => void, finish: () => void) => {
        this.Record = record;
        this.Pause = pause;
        this.Finish = finish;
    };

    render() {
        return (
            <div className="recordingBox" ref={this._ref}>
                {!this.result && (
                    <RecordingView
                        forceTrackScreen={BoolCast(this.layoutDoc[this.fieldKey + '_trackScreen'])}
                        getControls={this.getControls}
                        setResult={this.setResult}
                        setDuration={this.setVideoDuration}
                        id={DocCast(this.rootDoc.proto)?.[Id] || ''}
                    />
                )}
            </div>
        );
    }
    static screengrabber: RecordingBox | undefined;
}
ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
    if (_readOnly_) return RecordingBox.screengrabber ? true : false;
    if (RecordingBox.screengrabber) {
        RecordingBox.screengrabber.Pause?.();
        setTimeout(() => {
            RecordingBox.screengrabber?.Finish?.();
            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
            RecordingBox.screengrabber!.rootDoc.overlayY = 100;
            RecordingBox.screengrabber = undefined;
        }, 100);
    } else {
        const screengrabber = Docs.Create.WebCamDocument('', {
            _width: 384,
            _height: 216,
        });
        screengrabber.overlayX = -400;
        screengrabber.overlayY = 0;
        screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
        Doc.AddToMyOverlay(screengrabber);
        DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
            RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
            RecordingBox.screengrabber.Record?.();
        });
    }
}, 'toggle recording');
