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, StrListCast } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { NumCast, ScriptCast, StrCast, BoolCast, DocCast, RTFCast, Cast} 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 { LinkManager } from '../../util/LinkManager';
// import Card from 'react-bootstrap/Card';
import { DocumentType } from '../../documents/DocumentTypes';
import { forEach } from 'lodash';
import { SnappingManager } from '../../util/SnappingManager';
import { List } from '../../../fields/List';
import { gptAPICall, gptImageLabel } from '../../apis/gpt/GPT';
import { GPTCallType } from '../../apis/gpt/GPT';
import { ImageField, PdfField, URLField } from '../../../fields/URLField';
import { GPTPopup } from '../pdf/GPTPopup/GPTPopup';
import { GPTPopupMode } from '../pdf/GPTPopup/GPTPopup';
import { reaction } from 'mobx';
import { NumListCast } from '../../../fields/Doc';
import { undoBatch } from '../../util/UndoManager';
import { CalendarContainer } from 'react-datepicker';
@observer
export class CollectionCardView extends CollectionSubView() {

    @observable hoveredNodeIndex = -1;

    //key is the index in the child pair list, value is the id# for the group its in
    @observable customGroupDictionary: Map<number, number>[] = [new Map<number, number>(), new Map<number, number>(), new Map<number, number>()];

    /**
     * The child documents to be rendered-- either all of them except the Links or the docs in the currently active 
     * custom group
     */
    @computed get myChildLayoutPairs() {
        let activeGroups = NumListCast(this._props.Document.visibleGroupNumbers);
        let currCustom = NumCast(this._props.Document.customSortNumber);

        if (activeGroups.length <= 0) {
            return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK);
        }

        if (StrCast(this._props.Document.cardSort).includes("custom")) {
            return this.childLayoutPairs.filter((l, index) => {
                if (l.layout.type === DocumentType.LINK) {
                    return false;
                }
                // Get the group number for the current index from the customGroupDictionary
                const groupNumber = this.getButtonGroup(currCustom, l.layout)
                // Check if the group number is in the active groups
                return groupNumber !== undefined && activeGroups.includes(groupNumber);
            });
        }

        // Default return for non-custom cardSort or other cases, filtering out links
        return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK);
    }


    @action
    setHoveredNodeIndex = (index: number) => {
        if (!this.isSelected(index)) {
            this.hoveredNodeIndex = index;
        }
    };
    /**
     * Translates the hovered node to the center of the screen
     * @param index 
     * @returns 
     */
    translateHover = (index: number): number => {
        if (this.hoveredNodeIndex == index && !this.isSelected(index)) {
            return -50;
        }
        return 0;
    };

    @action
    setSelectedNodeIndex = (index: number) => {
        const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);
        if (SelectionManager.IsSelected(docs[index])) {
            this.setSelectedNodeIndex(index);
        }
    };

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

    /**
     * Returns all the documents except the one that's currently selected
     */
    inactiveDocs = () => {
        const docs = this.myChildLayoutPairs;    
        return docs.filter(d => !SelectionManager.IsSelected(d.layout));   
    };

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

    constructor(props: any) {
        super(props);
        makeObservable(this);
        const pairs = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK);

        //gets the values from the last time the view was loaded and puts them into their respective places in the hashmaps(s)
        for (let i=0; i< pairs.length; i++){
            if (pairs[i].layout.custom1Group != undefined){
                this.customGroupDictionary[0].set(i, NumCast(pairs[i].layout.custom1Group))
            }

            if (pairs[i].layout.custom2Group != undefined){
                this.customGroupDictionary[1].set(i, NumCast(pairs[i].layout.custom2Group))
            }

            if (pairs[i].layout.custom3Group != undefined){
                this.customGroupDictionary[2].set(i, NumCast(pairs[i].layout.custom3Group))
            }

            if (pairs[i].layout.chatGroup != undefined){
                this.gptGroups.set(pairs[i].layout, NumCast(pairs[i].layout.chatGroup))
                this.amGPTGroups = NumCast(this._props.Document.chatAmGroups)

            }
        }
        reaction(
            () => this._props.Document.cardSort,
            (cardSort) => {
                if (cardSort === 'chat') {
                    this.openChatPopup();
                }
            }
        );
    }

    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() {
        if (this.myChildLayoutPairs.length < this.maxRowCount) {
            length = this.myChildLayoutPairs.length;
        } else {
            length = this.maxRowCount;
        }
        return (this.childDocumentWidth * 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);

    /**
     * Returns the degree to rotate a card dependind on the amount of cards in their row and their index in said row
     * @param amCards 
     * @param index 
     * @returns 
     */
    rotate = (amCards: number, index: number) => {
        const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2));
        const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2)));

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

        return possRotate;
    };
    /**
     * Returns the degree to which a card should be translated in the y direction for the arch effect
     */
    translateY = (amCards: number, index: number, realIndex: number) => {
        const evenOdd = amCards % 2;
        const apex = (amCards - evenOdd) / 2;
        const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25);
        let rowOffset = 0;

        if (realIndex > this.maxRowCount - 1) {
            rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount);
        }
        if (evenOdd == 1 || index < apex - 1) {
            return Math.abs(stepMag * (apex - index)) - rowOffset;
        } else {
            if (index == apex || index == apex - 1) {
                return 0 - rowOffset;
            }

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

    /**
     * Translates the selected node to the middle fo the screen
     * @param index 
     * @returns 
     */
    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 - scaledNodeWidth - scaledNodeWidth / 4;

        return translation;
    };

    /**
     * Determines the order in which the cards will be rendered depending on the current sort type
     */
    @computed get sortedDocsType() {
        const desc = BoolCast(this.layoutDoc.sortDesc);
        let sorted = [];
        let docs = [];
    
        for (let i = 0; i < this.myChildLayoutPairs.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.myChildLayoutPairs[i];
        }
    
        switch (this._props.Document.cardSort) {
            case 'type':
                // Copy and sort documents by type
                return this.sort(sorted, 'type', desc);
            case 'color':
                return this.sort(sorted, 'color', desc);
            case 'custom':
                return this.sort(sorted, 'custom', desc);
            case 'chat':
                return this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc));            
                
            default:
                docs = this.myChildLayoutPairs;
                return { docs };
        }
    }
     /**
      * Converts a hex # to its hsv color value
      * @param hex 
      * @returns 
      */
    hexToHsv = (hex: string): [number, number, number] => {
        if (!hex) return [0, 0, 0]; // Default to black if hex is not defined
        const r = parseInt(hex.slice(1, 3), 16) / 255;
        const g = parseInt(hex.slice(3, 5), 16) / 255;
        const b = parseInt(hex.slice(5, 7), 16) / 255;
        const max = Math.max(r, g, b),
            min = Math.min(r, g, b);
        const d = max - min;
        let h: number;
        const s = max === 0 ? 0 : d / max;
        const v = max;

        switch (max) {
            case min:
                h = 0;
                break;
            case r:
                h = (g - b) / d + (g < b ? 6 : 0);
                break;
            case g:
                h = (b - r) / d + 2;
                break;
            case b:
                h = (r - g) / d + 4;
                break;
            default:
                h = 0;
                break;
        }
        h /= 6;
        return [h, s, v];
    };
    /**
     * Called in the sortedDocsType method. Compares the cards' value in regards to the desired sort type-- earlier cards are move to the
     * front, latter cards to the back
     * @param docs 
     * @param sortType 
     * @param isDesc 
     * @returns 
     */
    sort = (docs: { layout: Doc; data: Doc }[], sortType: string, isDesc: boolean) => {
        docs.sort((docA, docB) => {
            let typeA;
            let typeB;

            switch (sortType) {
                case 'color':
                    typeA = this.hexToHsv(StrCast(docA.layout.backgroundColor)) ?? ''; // If docA.type is undefined, use an empty string
                    typeB = this.hexToHsv(StrCast(docB.layout.backgroundColor)) ?? ''; // If docB.type is undefined, use an empty string
                    break;

                case 'custom':
                    typeA = this.getButtonGroup(NumCast(this._props.Document.customSortNumber), docA.layout) ?? '9999'
                    typeB = this.getButtonGroup(NumCast(this._props.Document.customSortNumber), docB.layout) ?? '9999'
                    break;   
                    
                case 'gpt':
                    typeA = this.getButtonGroup(99999, docA.layout, true) ?? '9999';
                    typeB = this.getButtonGroup(99999, docB.layout, true) ?? '9999';
                    break;  

                default:
                    typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string
                    typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string
                    break;
            }

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

        return { docs };
    };


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

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

    @observable maxRowCount = 10;

    /**
     * Determines how many cards are in the row of a card at a specific index
     * @param index 
     * @returns 
     */
    overflowAmCardsCalc(index: number) {
        if (this.inactiveDocs().length < this.maxRowCount) {
            return this.inactiveDocs().length;
        }
        // 13 - 3 = 10
        const totalCards = this.inactiveDocs().length;
        // if 9 or less
        if (index < totalCards - (totalCards % 10)) {
            return this.maxRowCount;
        }
        //(3)
        return totalCards % 10;
    }
    /**
     * Determines the index a card is in in a row
     * @param realIndex 
     * @returns 
     */
    overflowIndexCalc(realIndex: number) {
        if (realIndex < 10) {
            return realIndex;
        }

        return realIndex % 10;
    }
    /**
     * Translates the cards in the second rows and beyond over to the right
     * @param realIndex 
     * @param calcIndex 
     * @param calcRowCards 
     * @returns 
     */
    translateOverflowX(realIndex: number, calcIndex: number, calcRowCards: number) {
        
        if (realIndex < this.maxRowCount) {
            return 0;
        }

        return (10 - calcRowCards) * (this.panelWidth() / 2);
    }
    /**
     * Determines how far to translate a card in the y direction depending on its index, whether or not its being hovered, or if it's selected
     * @param isHovered 
     * @param isSelected 
     * @param realIndex 
     * @param amCards 
     * @param calcRowIndex 
     * @returns 
     */
    calculateTranslateY(isHovered: boolean, isSelected: boolean, realIndex: number, amCards: number, calcRowIndex: number) {
        let trans = 0;
        if (isHovered) {
            trans += this.translateHover(realIndex);
        }

        trans += this.translateY(amCards, calcRowIndex, realIndex);
        if (isSelected) {
            trans = 50 * this.fitContentScale;
        }
        return trans;
    }

    @observable _forceChildXf = false;

    /**
     * Actually renders all the cards
     */
    @computed get contentSorted() {
        const sortedDocs = this.sortedDocsType.docs;
        // Map sorted documents to their rendered components
        return sortedDocs.map((childPair, index) => {

            const isHovered = this.hoveredNodeIndex === index;
            const childPairIndex  = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK).indexOf(childPair)
            const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair);
            const calcRowIndex = this.overflowIndexCalc(realIndex);

            const amCards = this.overflowAmCardsCalc(realIndex);

            const isSelected = SelectionManager.IsSelected(childPair.layout);

            const childScreenToLocal = () => {
                this._forceChildXf;
                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, calcRowIndex) : 0);
            };

            return (
                <div
                    key={childPair.layout[Id]}
                    className={`card-item${isSelected ? '-active' : ''}`}
                    onPointerUp={e => {
                        SnappingManager.SetIsResizing(this.Document);
                        setTimeout(
                            action(() => {
                                SnappingManager.SetIsResizing(undefined);
                                this._forceChildXf = !this._forceChildXf;
                            }),
                            700
                        );
                    }}
                    style={{
                        width: this.panelWidth(),
                        height: this.panelHeight(childPair.layout)(),
                        transform: `
                        translateY(${this.calculateTranslateY(isHovered, isSelected, realIndex, amCards, calcRowIndex)}px)
                        translateX(${isSelected ? this.translateSelected(calcRowIndex) : this.translateOverflowX(realIndex, calcRowIndex, amCards)}px)
                        rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg)
                        scale(${isSelected ? 1.25 : 1})
                        `,
                    }}
                    onMouseEnter={() => this.setHoveredNodeIndex(index)}>
                    {this.displayDoc(childPair, childScreenToLocal)}

                    {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex, childPair.layout, false) : ''}
                    {this._props.Document.cardSort == 'chat' ? this.renderButtons(childPairIndex, childPair.layout, true) : ''}

                </div>
            );
        });
    }

    /**
     * Toggles the buttons between on and off when creating custom sort groupings/changing those created by gpt 
     * @param childPairIndex 
     * @param buttonID 
     * @param isChat 
     * @param doc 
     */
  
    @undoBatch
    @action toggleButton(childPairIndex: number, buttonID: number, isChat = false, doc: Doc) {
        if (!isChat) {
            const sortNumber = NumCast(this._props.Document.customSortNumber)
            this.customGroupDictionary[sortNumber].set(childPairIndex, buttonID)
            switch (sortNumber){
                case 0:
                    doc.custom1Group = buttonID
                    break
                case 1:
                    doc.custom2Group = buttonID
                    break
                case 2:
                    doc.custom3Group = buttonID
                    break
                default:
                    break
            }
        }
    
        if (isChat && doc) {
            this.gptGroups.set(doc, buttonID);
            doc.chatGroup = buttonID
        }
    }
    
    /**
     * A list of the text content of all the child docs. RTF documents will have just their text and pdf documents will have the first 50 words. 
     * Image documents are converted to bse64 and gpt generates a description for them. all other documents use their title. This string is
     * inputted into the gpt prompt to sort everything together 
     * @returns 
     */
    async childPairStringList(): Promise<string> {
        let string = "";
        for (let i = 0; i < this.childDocs.length; i++) {
            switch (this.childDocs[i].type) {
                case DocumentType.IMG:
                    string += `======${await this.getImageDesc(this.childDocs[i])}======`;
                    break;
    
                case DocumentType.PDF:
                    let pdfText = StrCast(this.childDocs[i].text);
                    let words = pdfText.split(/\s+/);
                    let first50Words = words.slice(0, 50);
                    string += `======${first50Words.join(' ')}======`;
    
                    this.textToDoc.set(first50Words.join(' ').trim(), this.childDocs[i]);
                    break;
    
                case DocumentType.RTF:
                    let rtfText = StrCast((RTFCast(this.childDocs[i].text)).Text);
                    string += `======${StrCast((RTFCast(this.childDocs[i].text)).Text)}======`;
                    this.textToDoc.set(rtfText.trim(), this.childDocs[i]);
                    break;
    
                default:
                    string += `======${StrCast(this.childDocs[i].title)}======`;
                    this.textToDoc.set(StrCast(this.childDocs[i].title).trim(), this.childDocs[i]);
            }
        }
        return string;
    }

    @observable isLoading = false
    
   
    imageUrlToBase64 = async (imageUrl: string): Promise<string> => {
        try {
            const response = await fetch(imageUrl);
            const blob = await response.blob();
    
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(blob); 
                reader.onloadend = () => resolve(reader.result as string); 
                reader.onerror = error => reject(error); 
            });
        } catch (error) {
            console.error('Error:', error);
            throw error; 
        }
    };

    textToDoc = new Map<string, Doc>()
    gptProccessedImages = new Set<Doc>()

    /**
     * Calls the gpt API to generate descriptions for the images in the view
     * @param image 
     * @returns 
     */
    @action async getImageDesc(image: Doc) {
        if (this.gptProccessedImages.has(image)) {
            // Return the already processed description
            return Array.from(this.textToDoc.keys()).find(key => this.textToDoc.get(key) === image) || '';
        }
    
        let href = (image['data'] as URLField).url.href;
        let hrefParts = href.split('.');
        let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
        try {
            let hrefBase64 = await this.imageUrlToBase64(hrefComplete);
            let response = await gptImageLabel(hrefBase64);
            this.textToDoc.set(response.trim(), image);
            this.gptProccessedImages.add(image);
            console.log(response);
            return response; // Return the response from gptImageLabel
        } catch (error) {
            console.log("bad things have happened");
        }
    }

    //child doc to its group determind by gpt
    gptGroups = new ObservableMap<Doc, number>
    @observable amGPTGroups = 0
    
    /**
     * Converts the gpt output into a hashmap that can be used for sorting. lists are seperated by ==== while elements within the list are seperated by ~~~~~~
     * @param gptOutput 
     */
    processGptOutput(gptOutput: string) {

        // Split the string into individual list items
        const listItems = gptOutput.split('======').filter(item => item.trim() !== '');
        this.amGPTGroups = listItems.length
        this._props.Document.chatAmGroups = this.amGPTGroups

        listItems.forEach((item, index) => {
            // Split the item by '~~~~~~' to get all descriptors
            const parts = item.split('~~~~~~').map(part => part.trim());

            parts.forEach(part => {
                console.log(part + "part")
                // Find the corresponding Doc in the textToDoc map
                if (this.textToDoc.has(part)) {
                    const doc = this.textToDoc.get(part);
                    if (doc) {
                        this.gptGroups.set(doc, index);
                        doc.chatGroup = index
                    }
                }
            });
        });
    }

    @observable isChatPopupOpen = false;
    /**
     * Opens up the chat popup and starts the process for smart sorting. 
     */
    @action openChatPopup = async () => {
        this.isChatPopupOpen = true;
        GPTPopup.Instance.setVisible(true);
        GPTPopup.Instance.setMode(GPTPopupMode.SORT);
        
        // Await the promise to get the string result
        const sortDesc = await this.childPairStringList();
        GPTPopup.Instance.setCardsDoneLoading(true); // Set dataDoneLoading to true after data is loaded
        GPTPopup.Instance.setSortDesc(sortDesc);
        GPTPopup.Instance.onSortComplete = this.handleGptSortResult;
};
    @action handleGptSortResult = (sortResult: string) => {
        this.processGptOutput(sortResult);
    };

    /**
     * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups 
     * @param childPairIndex 
     * @param doc 
     * @param isChat 
     * @returns 
     */
    renderButtons(childPairIndex: number, doc: Doc, isChat = false) {
        const buttons = [];
        const groupNumber = NumCast(this._props.Document.customSortNumber);
    
        let amButtons = 4;
        let activeButtonIndex = this.getButtonGroup(groupNumber, doc)
    
        if (isChat && doc) {
            if (this.amGPTGroups > 4){
                amButtons = this.amGPTGroups;
            }
            activeButtonIndex = this.getButtonGroup(9999, doc, true);
        }
    
        for (let i = 0; i < amButtons; i++) {
            const isActive = activeButtonIndex === i;
            buttons.push(
                <button
                    key={i}
                    style={{ backgroundColor: isActive ? '#4476f7' : '#323232' }}
                    onClick={() => this.toggleButton(childPairIndex, i, isChat, doc)}
                ></button>
            );
        }
    
        const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6;
        return (
            <div className="card-button-container" style={{ width: `${totalWidth}px` }}>
                {buttons}
            </div>
        );
    }

    getButtonGroup(groupNumber: number, doc: Doc, isChat?: boolean) {
        if (isChat){
            return NumCast(doc.chatGroup)
        }
        switch (groupNumber){
            case 0:
                return NumCast(doc.custom1Group)
            case 1:
                return NumCast(doc.custom2Group)
            case 2:
                return NumCast(doc.custom3Group)
            default:
                break
        }

        
    }


    @computed get translateWrapperX() {
        let translate = 0;

        if (this.inactiveDocs().length != this.myChildLayoutPairs.length && this.inactiveDocs().length < 10) {
            translate += this.panelWidth() / 2;
        }
        return translate;
    }
    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.contentSorted}
                </div>
            </div>
        );
    }
}
