import { ObservableMap, action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils';
import { Doc, DocListCast, Field } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { NumCast, ScriptCast, StrCast, BoolCast } from '../../../fields/Types';
import { DragManager } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
import { StyleProp } from '../StyleProvider';
import { DocumentView } from '../nodes/DocumentView';
import './CollectionCardDeckView.scss';
import { CollectionSubView } from './CollectionSubView';
import { Transform } from '../../util/Transform';
// import Card from 'react-bootstrap/Card';


@observer
export class CollectionCardView extends CollectionSubView() {
    @observable selectedNodeIndex = -1;

    @observable hoveredNodeIndex = -1;

    @action
    setHoveredNodeIndex = (index: number) => {
        if (!this.isSelected(index)) {
            this.hoveredNodeIndex = index;
        }
    };

    translateHover = (index: number): number => {
        if (this.hoveredNodeIndex == index && !this.isSelected(index)) {
            return -50 * this.fitContentScale;
        }
        return 0;
    };

    @action
    setSelectedNodeIndex = (index: number) => {
        const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);
        console.log('goodnight');

        if (SelectionManager.IsSelected(docs[index])) {
            console.log('good mornings');
            this.setSelectedNodeIndex(index);
        }
    };

    isSelected = (index: number): boolean => {
        const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);

        return SelectionManager.IsSelected(docs[index]);
    };

    inactiveDocs = () => {
        const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);



        return docs.filter(d => !SelectionManager.IsSelected(d));
    };

    middleIndex = Math.floor(this.inactiveDocs().length / 2);

    constructor(props: any) {
        super(props);
        makeObservable(this);
        // this.rotationDegree(7);
    }

    private _dropDisposer?: DragManager.DragDropDisposer;

    componentWillUnmount() {
        this._dropDisposer?.();
    }

    protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
        this._dropDisposer?.();
        if (ele) {
            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
        }
    };

    childDocumentWidth = 600; // target width of a Doc...
    /**
     * how much to scale down the contents of the view so that everything will fit
     */
    @computed get fitContentScale() {
        return (this.childDocumentWidth * this.childLayoutPairs.length) / this._props.PanelWidth();
    }
    panelWidth = () => this.childDocumentWidth;
    panelHeight = (layout: Doc) => () => (2 * (this.panelWidth() * NumCast(layout._height))) / NumCast(layout._width);
    onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
    isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive();
    isChildContentActive = () => (this.isContentActive() ? true : false);

    rotate = (amCards: number, index: number) => {
        console.log(amCards + "wtf")
        const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2));
        const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2)));

        // console.log(possRotate + "poss")

        if (amCards % 2 == 0 && possRotate == 0) {
            // console.log('whaddup');
            return possRotate + Math.abs(-30 + (index - 1) * (30 / (amCards / 2)));
        } else if (amCards % 2 == 0 && index > (amCards + 1) / 2) {
            // console.log("sup" + stepMag);

            return possRotate + stepMag;
        }

        return possRotate;
    };

    translateY = (amCards: number, index: number) => {
        const evenOdd = amCards % 2;
        const apex = (amCards - evenOdd) / 2;
        const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25);

        console.log('steo' + stepMag);

        if (evenOdd == 1 || index < apex - 1) {
            console.log('hi' + index);
            return Math.abs(stepMag * (apex - index));
        } else {
            if (index == apex || index == apex - 1) {
                return 0;
            }

            return Math.abs(stepMag * (apex - index - 1));
        }
    };

    translateOverFlowY = (amCards: number, index: number) => {
        if (amCards > 8 && index > amCards / 2) {
            return 100;
        }
        return 0;
    };

    translateSelected = (index: number): number => {
        if (this.isSelected(index)) {
            const middleOfPanel = this._props.PanelWidth() / 2;
            const scaledNodeWidth = this.panelWidth() * 1.25;

            // Calculate the position of the node's left edge before scaling
            const nodeLeftEdge = index * this.panelWidth();
            // Find the center of the node after scaling
            const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2;

            // Calculate the translation needed to align the scaled node's center with the panel's center
            const translation = middleOfPanel - scaledNodeCenter;

            return translation;
        }

        return 0;
    };

    @computed get sortedDocsType() {
        
        const desc = BoolCast(this.layoutDoc.sortDesc);

        let sorted = []

        for (let i=0; i< this.childLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list
            sorted[i] = this.childLayoutPairs[i]
        }


        // Copy and sort documents by type
        const docs = sorted.sort((docA, docB) => {
            const typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string
            const typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string

            // Perform a basic string comparison if types are strings
            let out = 0;
            if (typeA < typeB) out = -1;
            if (typeA > typeB) out = 1;
            if (desc) out *= -1; // Reverse the sort order if descending is true
            return out;
        });
        

        return { docs };
    }

    

   

    @observable docRefs = new ObservableMap<Doc, DocumentView>();

    @computed get contentSorted() {
        const sortedDocs = this.sortedDocsType.docs; 
        const amCards = this.inactiveDocs().length; 

        const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => {
            return (
                <DocumentView
                    {...this._props}
                    ref={action((r: DocumentView) => r?.ContentDiv && this.docRefs.set(childPair.layout, r))}
                    Document={childPair.layout}
                    TemplateDataDocument={childPair.data}
                    NativeWidth={returnZero}
                    NativeHeight={returnZero}
                    layout_fitWidth={returnFalse}
                    onDoubleClickScript={this.onChildDoubleClick}
                    renderDepth={this._props.renderDepth + 1}
                    LayoutTemplate={this._props.childLayoutTemplate}
                    LayoutTemplateString={this._props.childLayoutString}
                    ScreenToLocalTransform={screenToLocalTransform}
                    isContentActive={this.isChildContentActive}
                    isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive}
                    PanelWidth={this.panelWidth}
                    PanelHeight={this.panelHeight(childPair.layout)}
                />
            );
        };

        // Map sorted documents to their rendered components
        return sortedDocs.map((childPair, index) => {
            // const childPair = { layout: doc, data: doc }; 
            const isHovered = this.hoveredNodeIndex === index;
            const inactiveIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair);
            const isSelected = SelectionManager.IsSelected(childPair.layout);




            const childScreenToLocal = () => {
                const dref = this.docRefs.get(childPair.layout);
                const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv);
                return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0);
            };

            return (
                <div
                    key={childPair.layout[Id]}
                    className={`card-item${isSelected ? '-active' : ''}`}
                    style={{
                        width: this.panelWidth(),
                        height: this.panelHeight(childPair.layout)(),
                        transform: `
                            rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg)
                            translateY(${isHovered ? this.translateHover(inactiveIndex) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px)
                            translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px)
                            scale(${isSelected ? 1.25 : 1})
                        `,
                    }}
                    onMouseEnter={() => this.setHoveredNodeIndex(index)}>
                    {displayDoc(childPair, childScreenToLocal)}
                </div>
            );
        });
    }

    @computed get content() {
        // const currentIndex = NumCast(this.layoutDoc._carousel_index);
        const amCards = this.inactiveDocs().length;
        console.log(amCards + "lol")
        // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents

        // const myInactives =
        const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => {
            return (
                <DocumentView
                    {...this._props}
                    ref={action((r: DocumentView) => r?.ContentDiv && this.docRefs.set(childPair.layout, r))}
                    Document={childPair.layout}
                    TemplateDataDocument={childPair.data}
                    // onClickScript={this.toggleIcon}
                    //suppressSetHeight={true}
                    NativeWidth={returnZero}
                    NativeHeight={returnZero}
                    layout_fitWidth={returnFalse}
                    onDoubleClickScript={this.onChildDoubleClick}
                    renderDepth={this._props.renderDepth + 1}
                    LayoutTemplate={this._props.childLayoutTemplate}
                    LayoutTemplateString={this._props.childLayoutString}
                    // focus={this.focus}
                    ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot
                    isContentActive={this.isChildContentActive}
                    isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive}
                    PanelWidth={this.panelWidth}
                    PanelHeight={this.panelHeight(childPair.layout)}
                />
            );
        };

        return this.childLayoutPairs.map((childPair, index) => {
            const isSelected = this.isSelected(index);
            const isHovered = this.hoveredNodeIndex === index;
            const isOverflow = amCards > 8 && index > amCards / 2;
            // const  inactiveIndex = this.sortedDocsType.docs.indexOf(childPair);
            const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout);
            // const yOffset = this.verticalOffset(index);

            const childScreenToLocal = () => {
                const dref = this.docRefs.get(childPair.layout);
                const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv);
                // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform.  so we have to subtract that off
                return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0);
            };

            return (
                <div
                    key={childPair.layout[Id]}
                    className={`card-item${isSelected ? '-active' : ''}`}
                    style={{
                        width: this.panelWidth(),
                        height: this.panelHeight(childPair.layout)(),
                        transform: `
                            rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) 
                            translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px)
                            translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px)
                            scale(${isSelected ? 1.25 : 1})
                            
                            `, //scale has to be applied last or selected offset gets messed up
                    }}
                    // onClick={() => this.setSelectedNodeIndex(index)}

                    onMouseEnter={() => this.setHoveredNodeIndex(index)}>
                    {/* {this.lol(childPair.data, index)} */}

                    {displayDoc(childPair, childScreenToLocal)}
                </div>
            );
        });
    }

    @computed get translateWrapperX() {
        if (this.inactiveDocs().length != this.childLayoutPairs.length) {
            return this.panelWidth() / 2;
        }

        return 0;
    }

    @computed get renderCardsSort(){
        if (BoolCast(this._props.Document.card_sort_type) == true){
            return this.contentSorted
        }

        else{
            return this.content
        }
    }

    

    render() {
        return (
            <div
                className="collectionCardView-outer"
                ref={this.createDashEventsTarget}
                style={{
                    background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor),
                    color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
                }}>
                <div
                    className="card-wrapper"
                    style={{
                        transform: ` scale(${1 / this.fitContentScale}) translateX(${this.translateWrapperX}px)`,
                        transformOrigin: 'top left',
                        height: `${100 * this.fitContentScale}%`,
                    }}
                    onMouseLeave={() => this.setHoveredNodeIndex(-1)}>
                    {this.renderCardsSort}
                </div>

                {/* <Card  className={`custom-modal-position step-${step}`}>
                <Card.Header>
                    {header}
                    <Button variant="close" className= "tut-close"onClick={store.toggleTutorial} style={{ position: 'absolute', top: 0, right: 0 }} />
                </Card.Header>
                <Card.Body>{body}
                <Button className= 'next-step' variant="primary" onClick={store.nextStep}>Next Step!</Button>
                </Card.Body>


            </Card> */}

                {/* {this.focusContent} */}
            </div>
        );
    }
}
