import { action, observable, runInAction } 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, DocListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { BoolCast, Cast, DocCast } from '../../../../fields/Types';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { DocumentManager } from '../../../util/DocumentManager';
import { Docs } from '../../../documents/Documents';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
import { DocumentView } from '../DocumentView';
import { SettingsManager } from '../../../util/SettingsManager';
import { PropertiesView } from '../../PropertiesView';
import { PropertiesSection } from '../../PropertiesSection';
import { PropertiesDocContextSelector } from '../../PropertiesDocContextSelector';
import { listSpec } from '../../../../fields/Schema';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
import { AudioBox } from '../AudioBox';
import { UndoManager, undoBatch } from '../../../util/UndoManager';

@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);
        }
    };

    /**
     * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button
     * @param _readOnly_ 
     * @returns 
     */
    @undoBatch
    @action
    public static toggleWorkspaceRecording(_readOnly_: boolean) {
        if (_readOnly_) return RecordingBox.screengrabber ? true : false;
        if (RecordingBox.screengrabber) {
            //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
            console.log('grabbing screen!')
            RecordingBox.screengrabber.Pause?.();
            const remDoc = RecordingBox.screengrabber.rootDoc;
            setTimeout(() => {
                RecordingBox.screengrabber?.Finish?.();
                RecordingBox.screengrabber!.rootDoc.overlayX = 70; //was 100
                RecordingBox.screengrabber!.rootDoc.overlayY = 590;
                console.log(RecordingBox.screengrabber)
                RecordingBox.screengrabber = undefined;
            }, 100);
            //could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this
            setTimeout(() => {
                Doc.RemFromMyOverlay(remDoc);
    
            }, 1000)
            Doc.UserDoc().isRecording = false;
            Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
        } else {
            //when we first press mic
            const screengrabber = Docs.Create.WebCamDocument('', {
                _width: 205,
                _height: 115,
            });
            screengrabber.overlayX = 70; //was -400
            screengrabber.overlayY = 590; //was 0
            screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
            Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
            DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
                RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
                RecordingBox.screengrabber.Record?.();
            });
            Doc.UserDoc().isRecording = true;
        }
    }

    /**
     * This method changes the menu depending on whether or not we are in playback mode
     * @param value  RecordingBox rootdoc
     */
    @undoBatch
    @action
    public static toggleWorkspaceRecPlayback(value: Doc) {
        let docval = undefined;
        Doc.UserDoc().currentRecording = value;
        console.log(value)
        value.overlayX =70;
        value.overlayY = 590;
        if (!Doc.UserDoc().isAddRecToDocMode) {
            Doc.UserDoc().isRecPlayback = true;
            Doc.UserDoc().isWorkspaceRecPlaying = true;
            Doc.AddToMyOverlay(value);
            DocumentManager.Instance.AddViewRenderedCb(value, docView => {
                Doc.UserDoc().currentRecording = docView.ComponentView as RecordingBox;
                SelectionManager.SelectSchemaViewDoc(value);    
        })} else {
            let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value);
            DragManager.StartDropdownDrag([document.createElement('div')],new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
        }
    }

    /**
     * Adds the recording box to the canvas
     * @param value current recordingbox
     */
    @undoBatch
    @action
    public static addRecToWorkspace(value: RecordingBox) {
        console.log("adding rec to doc");
        console.log(value);
         let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
        (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value.rootDoc);
        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
        console.log(recordingIndex);
        Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
        Doc.UserDoc().isAddRecToDocMode = false;
        Doc.RemFromMyOverlay(value.rootDoc);
        Doc.UserDoc().currentRecording = undefined;
        Doc.UserDoc().isRecPlayback = false;
        Doc.UserDoc().isAddRecToDocMode = false;
        Doc.UserDoc().isWorkspaceRecPlaying = false;
        Doc.UserDoc().isWorkspaceRecPaused = false;
    }

    @undoBatch
    @action
    public static playWorkspaceRec(value: VideoBox) {
        value.Play();
        Doc.UserDoc().isWorkspaceRecPlaying = false;
        Doc.UserDoc().isWorkspaceRecPaused = true;
    }

    @undoBatch
    @action
    public static pauseWorkspaceRec(value: VideoBox) {
        value.Pause();
        Doc.UserDoc().isWorkspaceRecPlaying = true;
        Doc.UserDoc().isWorkspaceRecPaused = false;
    }

    @undoBatch
    @action
    public static closeWorkspaceRec(value: VideoBox) {
        value.Pause();
        Doc.RemFromMyOverlay(value.rootDoc);
        Doc.UserDoc().currentRecording = undefined;
        Doc.UserDoc().isRecPlayback = false;
        Doc.UserDoc().isWorkspaceRecPlaying = false;
        Doc.UserDoc().isWorkspaceRecPaused = false;
        Doc.RemFromMyOverlay(value.rootDoc);

    }

    @undoBatch
    @action
    public static removeWorkspaceRec(value: VideoBox) {
        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
        Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
        Doc.UserDoc().isAddRecToDocMode = false;
        Doc.RemFromMyOverlay(value.rootDoc);
        Doc.UserDoc().currentRecording = undefined;
        Doc.UserDoc().isRecPlayback = false;
        Doc.UserDoc().isAddRecToDocMode = false;
        Doc.UserDoc().isWorkspaceRecPlaying = false;
        Doc.UserDoc().isWorkspaceRecPaused = false;

    }

    

    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) { RecordingBox.toggleWorkspaceRecording(_readOnly_); });
ScriptingGlobals.add(function toggleRecPlayback(value: Doc) { RecordingBox.toggleWorkspaceRecPlayback(value); });
ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) { RecordingBox.addRecToWorkspace(value); });

ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) { RecordingBox.playWorkspaceRec(value); });
ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) { RecordingBox.pauseWorkspaceRec(value); });
ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) { RecordingBox.closeWorkspaceRec(value); });
ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) { RecordingBox.removeWorkspaceRec(value) });

ScriptingGlobals.add(function getWorkspaceRecordings() { return Doc.UserDoc().workspaceRecordings });
ScriptingGlobals.add(function getIsRecording() { return Doc.UserDoc().isRecording; })
ScriptingGlobals.add(function getIsRecPlayback() { return Doc.UserDoc().isRecPlayback; })
ScriptingGlobals.add(function getCurrentRecording() { return Doc.UserDoc().currentRecording; })
ScriptingGlobals.add(function getIsWorkspaceRecPlaying() { return Doc.UserDoc().isWorkspaceRecPlaying; })
ScriptingGlobals.add(function getIsWorkspaceRecPaused() { return Doc.UserDoc().isWorkspaceRecPaused; })


