/**
 * @author Martin Karkowski
 * @email m.karkowski@zema.de
 * @create date 2019-02-20 09:19:06
 * @modify date 2020-07-22 22:06:39
 * @desc [description]
 */

import React from 'react';
import { Col, Container, Modal, Nav, Row } from 'react-bootstrap';
import { FaTimesCircle } from 'react-icons/fa';
import DefaultNavbar from '../defaultNavbar';
import DynamicRenderer from '../dynamic/dynamicRenderer'
import { DynamicRendererProps } from '../dynamic/dynamicRenderer';
import Selection, { SelecitonProps } from './selection';

const mainStyle = {
    minHeight: '90vh',
}

const sidebarStyle = {
    padding: '10px',
    background: "primary"
}

const contentStyle = {
    padding: '10px',
}

export interface ITab {
    label: string,
    id: string,
    delteable: boolean
}

export interface LayoutProps<T> extends SelecitonProps<T> {
    onResize?: () => void;
    onMount?: (ref: React.RefObject<any>, layout: Layout<T>) => void;
    onUnmount?: () => void;
    onNewTab?: () => Promise<ITab | false>;
    onTabSelect?: (oldTabId: string, newTabId: string) => Promise<boolean>;
    onTabDelete?: (tabId: string) => Promise<boolean>;
    onNoTabSelected?: () => Promise<void>;
    tabs?: {
        allowNewTabs?: boolean;
        active: string,
        items: ITab[]
    }
}

export interface ModalSettings {
    content: DynamicRendererProps;
    header: string;
    size?: 'sm' | 'lg' | 'xl'
}

export interface LayoutState<T> {
    update: null
}

class Layout<T> extends React.Component<LayoutProps<T>, LayoutState<T>> {

    protected _ref: React.RefObject<any>;
    protected _handleResize: () => void;

    componentDidMount() {
        const _this = this;

        function handleResize() {
            if (typeof _this.props.onResize === 'function') {
                _this.props.onResize();
            }
        }

        if (typeof this.props.onMount === 'function') {
            this.props.onMount(this._ref, this);
        }

        this._handleResize = handleResize;
        window.addEventListener('resize', this._handleResize);
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this._handleResize);

        // Call the unmount
        if (typeof this.props.onUnmount === 'function') {
            this.props.onUnmount();
        }
    }

    constructor(props) {
        super(props);
        this._ref = React.createRef();
    }

    public requestRerender() {
        this.setState({
            update: null
        })
    }

    public openPopup(settings: ModalSettings){
        this._modalSettings = settings;
        this._modalVisible = true;

        this.requestRerender();

        const _this = this;
        return () => {
            _this._modalVisible = false;
            _this.requestRerender();
        }
    }

    protected _modalVisible = false;
    protected _modalSettings: ModalSettings;

    public render() {

        const _this = this;

        // Define a Select Tab Function.
        const selectTab = async (id: string) => {
            if (typeof this.props.onTabSelect === 'function') {
                // Call the Async Function to select a Tab.
                if (await this.props.onTabSelect(this.props.tabs.active, id)) {
                    this.props.tabs.active = id;
                    this.requestRerender();

                    return true;
                }

                return false;
            } else {
                // Assign the Tab ID
                this.props.tabs.active = id;
                this.requestRerender();

                return true;
            }
        }

        const delteTab = async (id: string, idx: number) => {

            let removed = false;
            if (typeof _this.props.onTabDelete === 'function') {
                // Call the Async Function to select a Tab.
                if (await _this.props.onTabDelete(id)) {
                    removed = true;
                }
            } else {
                removed = true;
            }

            if (removed) {
                // Remove the Items.
                _this.props.tabs.items.splice(idx, 1);

                // Check if the active element has been removed:
                if (id == _this.props.tabs.active) {

                    // Assign the ID of the Element.
                    const _idx = _this.props.tabs.items.length > idx ? idx : _this.props.tabs.items.length - 1;
                    
                    if (_idx !== -1){
                        // Assign the First ID.
                        const _newTabId = _this.props.tabs.items.length > _idx ? _this.props.tabs.items[_idx].id : null;

                        if (_newTabId !== null) {
                            if (!selectTab(_newTabId) && typeof _this.props.onNoTabSelected === 'function') {
                                // Send a Warning, that no Tabs has been selected
                                await _this.props.onNoTabSelected();
                            }
                        } else if (typeof _this.props.onNoTabSelected === 'function') {
                            // Send a Warning, that no Tabs has been selected
                            await _this.props.onNoTabSelected();
                        }
                    } else if (typeof _this.props.onNoTabSelected === 'function') {
                        // Send a Warning, that no Tabs has been selected
                        await _this.props.onNoTabSelected();
                    }
                }

                _this.requestRerender();
            }
            

            
        }

        return (<>
            <DefaultNavbar></DefaultNavbar>
            <Container fluid style={mainStyle}>
                <Row style={mainStyle}>
                    <Col className="col-md-2 d-none d-md-block bg-light sidebar-sticky" style={sidebarStyle}>
                        <Selection selection={this.props.selection} allowUserSelect={this.props.allowUserSelect} onItemSelected={this.props.onItemSelected}></Selection>
                    </Col>
                    <Col role="main" style={contentStyle}>
                        {this.props.tabs ?
                            <Nav variant="tabs" activeKey={this.props.tabs.active}>
                                {this.props.tabs.items.map((tab, idx) => {
                                    if (tab.delteable && this.props.tabs.allowNewTabs) {
                                        return (
                                            <Nav.Item key={tab.id}>
                                                <Nav.Link onSelect={_ => {
                                                    selectTab(tab.id);
                                                }} eventKey={tab.id}>{tab.label + ' '}
                                                    <FaTimesCircle onClick={
                                                        (e) => {
                                                            e.preventDefault();
                                                            e.stopPropagation();

                                                            delteTab(tab.id, idx);
                                                        }
                                                    } ></FaTimesCircle>
                                                </Nav.Link>
                                            </Nav.Item>
                                        );
                                    } else {
                                        return (
                                            <Nav.Item key={tab.id}>
                                                <Nav.Link onSelect={_ => {
                                                    selectTab(tab.id);
                                                }} eventKey={tab.id}>{tab.label}</Nav.Link>
                                            </Nav.Item>
                                        );
                                    }
                                })}

                                {this.props.tabs.allowNewTabs ?
                                    <Nav.Item>
                                        <Nav.Link eventKey='_NEW_ITEM' onSelect={async () => {
                                            if (typeof this.props.onNewTab === 'function') {
                                                const tab = await this.props.onNewTab();
                                                
                                                if (tab && typeof tab === 'object') {
                                                    this.props.tabs.items.push(tab);

                                                    selectTab(tab.id);
                                                }
                                            }
                                        }}>
                                            +
                                </Nav.Link>
                                    </Nav.Item> : ''
                                }

                            </Nav>
                            : ''
                        }

                        {/* style={{height: '100%'}} */}
                        <div ref={this._ref}></div>
                    </Col>
                </Row>
            </Container>
            {/* Render a Modal dynamically. */}
            {this._modalSettings != undefined?
                <Modal 
                    show={this._modalVisible} 
                    backdrop="static"
                    keyboard={false}
                    size={this._modalSettings.size}
                    centered
                >
                    <Modal.Header>
                        <Modal.Title>{this._modalSettings.header}</Modal.Title>
                    </Modal.Header>
                    <Modal.Body>
                            {/* Render the dynamic Component */}
                            <DynamicRenderer component={this._modalSettings.content.component} props={this._modalSettings.content.props}/>
                    </Modal.Body>
                </Modal>
            : ''}
        </>);
    }
}

export default Layout;