// Import the Lasal Runtime base element into your component
// Import SigPolymer to use Polymer methods: html, afterNextRender, beforeNextRender, debouncer, timeOut
// or if your component's getter template() returns a HTML literal
import { LasalRuntimeSigElement, SigPolymer } from '../../sigmatek/sig-element/sig-element.js';
// Import dependencies
import './moment/min/moment-with-locales.js';
/* import ('../../sigmatek/sig-utils-jquery/sig-utils-jquery.js').then(() => {
    import('./bootstrap-material-datetimepicker/js/bootstrap-material-datetimepicker.js');
}); */
// loadjs('../../../../rt/node_modules/jquery/dist/jquery.min.js', () =>
//     loadjs('/res/components/user/sig-control-datepicker/bootstrap-material-datetimepicker/js/bootstrap-material-datetimepicker.js')); 
loadjs.ready('jQuery', {
    success: () => {
        loadjs('/res/components/user/sig-control-datepicker/bootstrap-material-datetimepicker/js/bootstrap-material-datetimepicker.js', {
            before: (path, scriptElement) => {
                scriptElement.crossOrigin = 'use-credentials';
            }
        });
    }
});
import './sig-control-datepicker-picker-wrapper.js';
import '../sig-control-input/sig-control-input.js'
import '../sig-control-input/sig-control-input-css.js'


/****************************************************************************************************
 * @class LasalRuntimeSigDatepickerElement
 * @extends {LasalRuntimeSigElement}
 ****************************************************************************************************/
export class LasalRuntimeSigDatepickerElement extends LasalRuntimeSigElement {
    /****************************************************************************************************
     * When the element is loaded, importMeta() assigns reference to the path from 
     * which an element was imported to its importPath property. 
     * Relative URLs in styles are automatically re-written to be relative to the importPath property. 
     * You can use [[importPath]] in your component to load url resources
     ****************************************************************************************************/
    static get importMeta() {
        return import.meta;
    }

    /****************************************************************************************************
     * Return the component style and template as a template literal
     ****************************************************************************************************/
    static get template() {
        return SigPolymer.html`
        <style include="sig-element-css sig-control-input-css">
            :host {
                /* Basic styling of the component */
                color: var(--theme-sig-control-datepicker-color, rgba(160, 160, 160, 1));

                border-radius: var(--theme-sig-control-datepicker-border-radius, 0);
                border-top-left-radius: var(--theme-sig-control-datepicker-border-radius-tl, var(--theme-sig-control-datepicker-border-radius, 0));
                border-top-right-radius: var(--theme-sig-control-datepicker-border-radius-tr, var(--theme-sig-control-datepicker-border-radius, 0));
                border-bottom-right-radius: var(--theme-sig-control-datepicker-border-radius-br, var(--theme-sig-control-datepicker-border-radius, 0));
                border-bottom-left-radius: var(--theme-sig-control-datepicker-border-radius-bl, var(--theme-sig-control-datepicker-border-radius, 0));

                /* Basic box model settings */
                display: block;
                position: absolute;
                overflow: hidden;
            }

            :host * {
                /* Reset margins and paddings for child elements and turn of text selection */
                @apply --notextselect;
                margin: 0;
                padding: 0;
            }

            .clearfix:after {
                @apply --clearfix
            }

            .sig-control-datepicker-base {
                color: inherit;
                display: table;
                width: 100%;
                height: 100%;
                position: relative;

                box-sizing: inherit;
                text-decoration: inherit;
                border: none;
                cursor: pointer;
            }

            #testInput {
                /* height: 100px;
                width: 200px; */
                /* background-color: red; */
            }

            :host .sig-control-datepicker-base sig-control-input {
                position: absolute;
                top: 0;
                left: 0;
                height: 100%;
                width: 100%;

                --theme-sig-control-input-color: var(--theme-sig-control-datepicker-input-color, inherit);
                --theme-sig-control-input-background-color:var(--theme-sig-control-datepicker-input-background-color, inherit);
                --theme-sig-control-input-value-background-color:var(--theme-sig-control-datepicker-input-value-background-color, rgba(196, 192, 192, 1));
                --theme-sig-control-input-value-active-color:var(--theme-sig-control-datepicker-input-value-active-color, inherit);
                --theme-sig-control-input-value-active-background-color:var(--theme-sig-control-datepicker-input-value-active-background-color, inherit);


                --theme-sig-control-input-font-size:var(--theme-sig-control-datepicker-input-font-size, 11px);
                --theme-sig-control-input-border-color:var(--theme-sig-control-datepicker-input-border-color, inherit);
                --theme-sig-control-input-border-width:var(--theme-sig-control-datepicker-input-border-width, 1px);
                --theme-sig-control-input-border-style:var(--theme-sig-control-datepicker-input-border-style, solid);
                --theme-sig-control-input-border-radius: var(--theme-sig-control-datepicker-input-border-radius, 3px);
                --theme-sig-control-input-margin-leftright:var(--theme-sig-control-datepicker-input-margin-leftright, 0px);
                --theme-sig-control-input-margin-top:var(--theme-sig-control-datepicker-input-margin-top, 0px);

                --theme-sig-control-input-value-text-align: var(--theme-sig-control-datepicker-input-unit-text-align, center);
                --theme-sig-control-input-unit-vertical-align: var(--theme-sig-control-datepicker-input-unit-vertical-align, center);
            }
        </style>

        <div class="sig-control-datepicker-base clearfix">
            <sig-control-input id="testInput" on-tap="_tapHandler"></sig-control-input> 
        </div>
        `;
    }



    /****************************************************************************************************
     * define the custom tag name 
     ****************************************************************************************************/
    static get is() {
        return "sig-control-datepicker";
    }

    /****************************************************************************************************
     * define the main porperties of the component
     * reflected property names should always be lower case so it can be used directly on the element as an attribute
     ****************************************************************************************************/
    static get properties() {
        // property names should always be lower case so we
        // can use them directly on the element as an attribute
        let props = {
            value: {
                type: String,
                value: "",
                notify: true,
                observer: "_valueChanged"
            },
            datepickerid: {
                type: String,
                value: undefined,
            },
            windowed: {
                type: Boolean,
                value: false
            },
            dateformat: {
                type: String,
                value: 'DD.MM.YYYY',
                observer: '_designModeUpdatePlacehoder'
            },
            mindate: {
                type: String,
                value: ''
            },
            maxdate: {
                type: String,
                value: ''
            },
            /*Window Settings */
            windowtop: {
                type: Number,
                value: 0
            },
            windowleft: {
                type: Number,
                value: 0
            },
            hdrbgcolor: {
                type: String,
                value: undefined
            },
            panelcontentbgcolor: {
                type: String,
                value: undefined
            }/* ,
            hdrcolor: {
                type: String,
                value: undefined
            },
            hdrheight: {
                type: String,
                value: undefined
            },
            hdrtextalign: {
                type: String,
                value: undefined
            },
            windowbordercolor: {
                type: String,
                value: undefined
            },
            windowborderwidth: {
                type: String,
                value: undefined
            },
            windowborderstyle: {
                type: String,
                value: undefined
            },
            windowborderradius: {
                type: String,
                value: undefined
            },
            windowiconsize: {
                type: String,
                value: undefined
            },
            windowiconpaddinghorizontal: {
                type:String,
                value: undefined
            },
            windowboxshadow: {
                type: String,
                value: undefined
            },
            windowheaderlogo: {
                type: String,
                value: undefined
            }, */
            /*/Window Settings */
            ,
            windowtitle: {
                type: String,
                value: "",
                observer: '_windowTitleChanged'
            },
            datepickerfont: {
                type: Object,
                value: () => {return {}},
            }
        }
        return props;
    }

    /****************************************************************************************************
     * Called when the element has been created,
     * but before property values are set and local DOM is initialized.
     ****************************************************************************************************/
    constructor() {
        super();

        this.dispatchAllInternalEvents = true;

        this.wrapper = undefined;
        this.inputWindow = undefined;

        this.wmApi = window.sigApi.windowManager;
        this.datepicker = undefined;

        this.renderedCB = undefined;
        this.propReady = undefined;

        this.hidePicker = true;

        //default format
        this.defaultDateFormat = 'DD.MM.YYYY';
        
        window.sigApi.vm.addRenderCallback(this, () => {
            this._renderCallback();
        }, () => {
            this._errorRenderCallback();
        })
        
        this.sigAddRequiredProperty('windowed');
        this.sigAddRequiredProperty('dateformat');

        this.wrapperProps = [
            "--theme-sig-control-datepicker-wrapper-background-color",
            "--theme-sig-control-datepicker-wrapper-border-color",
            "--theme-sig-control-datepicker-wrapper-border-width",
            "--theme-sig-control-datepicker-wrapper-border-style",
            "--theme-sig-control-datepicker-wrapper-border-radius",
            "--theme-sig-control-datepicker-wrapper-header-background-color",
            "--theme-sig-control-datepicker-wrapper-header-color",
            "--theme-sig-control-datepicker-wrapper-month-header-color",
            "--theme-sig-control-datepicker-wrapper-header-symbols-color",
            "--theme-sig-control-datepicker-wrapper-calendar-width",
            "--theme-sig-control-datepicker-wrapper-inactive-days-color",
            "--theme-sig-control-datepicker-wrapper-active-days-color",
            "--theme-sig-control-datepicker-wrapper-selected-text-color",
            "--theme-sig-control-datepicker-wrapper-selected-color",
            "--theme-sig-control-datepicker-wrapper-table-header-color",
            "--theme-sig-control-datepicker-wrapper-button-height",
            "--theme-sig-control-datepicker-wrapper-button-width",
            "--theme-sig-control-datepicker-wrapper-button-border-color",
            "--theme-sig-control-datepicker-wrapper-button-border-width",
            "--theme-sig-control-datepicker-wrapper-button-border-style",
            "--theme-sig-control-datepicker-wrapper-button-border-radius",
            "--theme-sig-control-datepicker-wrapper-button-background-color",
            "--theme-sig-control-datepicker-wrapper-button-pressed-background-color",
            "--theme-sig-control-datepicker-wrapper-button-color",
            "--theme-sig-control-datepicker-wrapper-button-pressed-color"]
    }

    /****************************************************************************************************
     * Called when the required properties are set
     *
     ****************************************************************************************************/
    sigOnRequiredPropertiesReady() {
        super.sigOnRequiredPropertiesReady();
        this.propReady = true;
        this._setupDatepicker();
    }


    /****************************************************************************************************
     *  called after property default values are set and local DOM is initialized
     ****************************************************************************************************/
    ready() {
        super.ready();
        this.$.testInput._showKeyboard = () => { return };
        this.$.testInput.onchange = (ev, date) => {
            this._inputValueChanged(date);
        }
        /* this.sigAddEventListener('change', () => {
            this._inputValueChanged()
        }, 'jsEvent', this.$.testInput);
 */
        this.sigAddEventListener('LANGUAGE_CHG', () => {
            this._langChangeHandler()
        }, 'runtimeEvent');
    }

    /****************************************************************************************************
     * Handles language change events
     * Removes the date picker, and renders it new
     ****************************************************************************************************/
    _langChangeHandler() {
        $(this.$.testInput).bootstrapMaterialDatePicker('destroy');
        //remove datepicker
        if (this.datepicker) {
            this.datepicker.remove();
            this.datepicker = undefined;
        }
        this.hidePicker = true;
        this.$.testInput.iskeyboardopen = false;
        if(this.wrapper) {
            this.wrapper.remove();
            this.wrapper = undefined;
        }

        if(this.inputWindow) {
            this.inputWindow.remove();
            this.inputWindow = undefined;
        }
        this._setupDatepicker();
    }

    /****************************************************************************************************
     * Eventhandles when the value of the input text field changes
     ****************************************************************************************************/
    _inputValueChanged(date) {
        //check if date available
        if (!date) {
            date = moment(this.$.testInput.value, this.dateformat ? this.dateformat : this.defaultDateFormat);
        }
        this.value = date.format(this.defaultDateFormat);
    }

    /****************************************************************************************************
     * Called when the component is rendered
     ****************************************************************************************************/
    _renderCallback() {
        this.renderedCB = true;
        this._setupDatepicker();
    }

    /****************************************************************************************************
     * Initializes the datepicker
     ****************************************************************************************************/
    _setupDatepicker() {
        if(this.isdesignmode) {
            this._designModeUpdatePlacehoder();
            return;
        }

        if(!this.propReady || ! this.renderedCB || this.datepicker) {
            return;
        }

        let minDate, maxDate;
        if(this.mindate) {
            //minDate = moment(this.mindate, this.dateformat);
            minDate = moment(this.mindate, 'DD.MM.YYYY');
            if(!minDate.isValid()) {
                minDate = moment(0);
            }
        } else {
            minDate = moment(0);
        }

        if(this.maxdate) {
            //maxDate = moment(this.maxdate, this.dateformat);
            maxDate = moment(this.maxdate, 'DD.MM.YYYY');
            if(!maxDate.isValid()) {
                maxDate = moment(10000000000000);
            }
        } else {
            maxDate = moment(10000000000000);
        }

        //Initializes the bootstrapMaterialDatepicker
        $(this.$.testInput).bootstrapMaterialDatePicker({
            time: false,
            lang: this._getActiveLang(),
            format: this.dateformat ? this.dateformat : this.defaultDateFormat,
            defaultFormat: this.defaultDateFormat,
            dateTimePicker: this,
            // if a date isnt set, it is falsey, so we get to the part after the || and that is used as a default
            /* minDate: new Date(this.mindate || 0),
            maxDate: new Date(this.maxdate || 10000000000000), */
            minDate: minDate,
            maxDate: maxDate,
            year: false
        }).on('close', () => {
            this.$.testInput.iskeyboardopen = false;
            if(this.windowed === 'window') {
                if(this.inputWindow) {
                    this.inputWindow.close();
                }
            } else {
                this.wrapper.style.display = 'none';
            }
        });;

        this.datepickerid = this.$.testInput.getAttribute('data-dtp');
        this.datepicker = document.getElementById(this.datepickerid);
        this.datepicker.style.visibility = 'hidden';
        this.datepicker.style.position = 'absolute';
        this.wrapper = document.createElement('sig-control-datepicker-picker-wrapper');
        this.wrapper.reqNames = [];
        //gets the css variables that are meant for the wrapper
        const wrapperCSSText = this._getWrapperCSS();
        this.wrapper.style.cssText = wrapperCSSText;
        this._setWrapperFont();
        if (this.windowed === 'window') {
            this._setupWindowed();
        } else {
            this._setupDropdown();
        }
        window.sigApi.vm.addRenderCallback(this.wrapper, () => {
            if (this.windowed === 'window') {
                this._setupWindowed();
            } else {
                this._setupDropdown();
            }
        });

        //Finally call the value changed function
        // to set the input value to the value currently on the server
        this._valueChanged(this.value);
    }

    /****************************************************************************************************
     * Sets the font for the datepicker
     ****************************************************************************************************/
    _setWrapperFont() {
        const fontObjProp = window.sigApi.properties.getProperty(this.id, 'datepickerfont');
        if(fontObjProp) {
            const fontObj = fontObjProp.getValue();
            if(fontObj) {
                this.wrapper.updateStyles({
                    '--theme-sig-control-datepicker-wrapper-font-size': fontObj.size + 'px',
                    '--theme-sig-control-datepicker-wrapper-font-family': fontObj.fontFamily ? fontObj.fontFamily : 'inherit'
                })
            }
        }
    }

    /****************************************************************************************************
     * Sets the datepicker up for being opened in a window
     ****************************************************************************************************/
    _setupWindowed() {
        if(!this.inputWindow) {
            let windowId = `${this.id}-input-window`;
            //   Actually creating the window here
            //   @param top The top position
            //   @param left The left position
            //   @param width The width of the window
            //   @param height The height of the window content. The actual window should be slightly higher because there are still the close and minimize buttons
            //   @param callback Is called when the window is created, has a reference to the created window as variable
            //   @param props Properties of the window
            //   @param windowId The id of the window
            this.wmApi.createWindow(this.windowtop, this.windowleft, '100px', '100px', (win) => {
                this.inputWindow = win;
                this._appendWrapperToWindow();
                this._windowTitleChanged();
            }, this._getWindowProps(), windowId);
        } else {
            this._appendWrapperToWindow();
        }
    }

    /****************************************************************************************************
     *adds the wrapper to the window
     *
     ****************************************************************************************************/
    _appendWrapperToWindow() {
        this.inputWindow.style.visibility = 'hidden';
        //   Disable resizing, so that the window stays the same size as its content
        this.inputWindow.resizeit('disable');
        //   Set the window rotation to its parents rotation
        this.inputWindow.style.transform = `rotate(${this.rotation}deg)`
        //Make sure the window is in front
        this.sigSetTimeout(this.inputWindow.front, 100);
        //   Add the Input to the Window
        if(!this.wrapper.options) {
            this.wrapper.options = {};
        }
        this.wrapper.options.type = 'window'
        this.inputWindow.querySelector('.jsPanel-content').appendChild(this.wrapper);
        window.sigApi.vm.addRenderCallback(this.wrapper, () => {
            this.wrapper.datepickerid = this.datepickerid;
            this.wrapper.datepicker = this.datepicker;
            this._setWrapperFont();
            this.wrapper._addDatepicker();
            this.wrapper.parent = this;
            this.wrapper._setControlPosition();
            this.inputWindow.close();
            this.inputWindow.style.removeProperty('visibility');
        }, () => {
            this._log('Error Render');
        }); 
    }

    /****************************************************************************************************
     * Sets the datepicker up for being opened as a dropdown
     ****************************************************************************************************/
    _setupDropdown() {
        //Get the container where the timepicker is added to
        let container = this.closest('.jsPanel-content');
        if(!container) {
            //container = this.closest('sig-app');
            container = document.querySelector('sig-app');
        }
        container.appendChild(this.wrapper);
        window.sigApi.vm.addRenderCallback(this.wrapper, () => {
            //After the datepicker wrapper has been renderd, add the datepicker to it, and set its position
            this.wrapper.datepickerid = this.datepickerid;
            this.wrapper.datepicker = this.datepicker;
            this._setWrapperFont();
            this.wrapper._addDatepicker();
            this.wrapper.parent = this;
            this.wrapper._setControlPosition();
            if(this.hidePicker) {
                this.wrapper.style.display = 'none';
            }
            
        }, () => {
            this._log('Error Render');
        });
    }

    /****************************************************************************************************
     * Parses the CSS that is meant for the wrapper out of the css of the component
     * @returns
     ****************************************************************************************************/
    _getWrapperCSS() {
        if (!this.wrapper) {
            return '';
        }
        const cs = getComputedStyle(this);
        let style = [];
        for(let prop of this.wrapperProps) {
            const value = cs.getPropertyValue(prop);
            if (value) style.push(prop + ':' + value);
        }
        return style.join(';');
    }

    /****************************************************************************************************
     * Called when there was an error rendering
     ****************************************************************************************************/
    _errorRenderCallback() {
        window.sigApi.vm.addRenderCallback(this, () => {
            this._renderCallback();
        }, () => {
            this._errorRenderCallback();
        })
    }

    /****************************************************************************************************
     * Handles a tap on the inputs
     ****************************************************************************************************/
    _tapHandler() {
        this.$.testInput.iskeyboardopen = true;
        this.hidePicker = false;
        this.datepicker.style.removeProperty('position');
        this.datepicker.style.removeProperty('visibility');
        $(this.$.testInput).bootstrapMaterialDatePicker('_fireCalendar');
        if(this.windowed === 'window') {
            if(this.inputWindow) {
                this.inputWindow.open();
                this.sigSetTimeout(this.inputWindow.front, 100);
                this.wrapper._setControlPosition();
                if(this.inputWindow.offsetWidth === 1) {
                    this.sigSetTimeout(() => {
                        //this.datepicker.classList.remove('hidden');
                        this._tapHandler()
                    }, 100);
                }
            }
        } else {
            this.wrapper.style.removeProperty('display');
            
            this.wrapper._setControlPosition();
        }

        let closeHandler = (e) => {
            if(e.target.tagName !== 'SIG-CONTROL-DATEPICKER-PICKER-WRAPPER') {
                this.$.testInput.iskeyboardopen = false;
                if(this.windowed === 'window') {
                    if(this.inputWindow) {
                        this.inputWindow.close();
                    }
                } else {
                    this.wrapper.style.display = 'none';
                }

                this.sigRemoveEventListener('down', closeHandler, 'polymerEvent', document.body);
            }
            
        }
        this.sigAddEventListener('down', closeHandler, 'polymerEvent', document.body);

    }

    /****************************************************************************************************
     * Returns a property object used for creating a window
     * @returns
     ****************************************************************************************************/
    _getWindowProps() {
        return {
            events: {
                jspanelbeforeclose: () => {
                    this.$.testInput.iskeyboardopen = false;
                }
            }
        };
    }

    /****************************************************************************************************
     * called after the element is detached from the DOM
     * can be called multiple times during the lifetime of an element
     *use this to cleanup your "mess" ;-) 
     ****************************************************************************************************/
    disconnectedCallback() {
        super.disconnectedCallback();

        if(this.datepicker instanceof HTMLElement) {
            this.datepicker.remove();
            this.datepicker = null;
        }

        if(this.wrapper instanceof HTMLElement) {
            this.wrapper.remove();
            this.wrapper = null;
        }

        if(this.inputWindow instanceof HTMLElement) {
            this.inputWindow.remove();
            this.inputWindow = null;
        }
    }

    /****************************************************************************************************
     * Called when the time on the Datapoint changes
     * @param {String} newval - The new Time 
     ****************************************************************************************************/
    _valueChanged(newval) {
        if(!this.wrapper || this.$.testInput.iskeyboardopen) {
            return;
        }
        if(this.value === undefined || this.value.length === 0 || this.value === 0 || (newval === '') || (newval === undefined)) {
            this.$.testInput.value = '';
            return;
        }
        const date = moment(this.value, 'DD.MM.YYYY');
        if(date.isValid()) {
            this.$.testInput.setAttribute('value', this.dateformat ? date.format(this.dateformat) : date.format(this.defaultDateFormat));
            $(this.$.testInput).bootstrapMaterialDatePicker('setDate', date);
        } else {
            this.value = '';
        }
    }
    /****************************************************************************************************
     * called when css variables are updated
     * updates the wrapper variables
     *
     * @param {*} cssObj
     * @param {boolean} [doBoundsCheck=false]
     ****************************************************************************************************/
    sigApplyCSSValue(cssObj, doBoundsCheck = false) {
        super.sigApplyCSSValue(cssObj, doBoundsCheck);
    
        if(this.wrapper) {
            let wrapperCSSText = this._getWrapperCSS();
            // Filter for inline styles that werent set via getWrapperCCSS()
            //They need to be added for correct positioning of the control
            const currentWrapperCss = this.wrapper.style.cssText;
            const currentWrapperCssArr = currentWrapperCss.split(';');
            const additionalWrapperCss = currentWrapperCssArr.filter((val) => {
                const trimmedVal = val.trim()
                return trimmedVal.indexOf('--theme-sig-control-') === -1;
            })
            wrapperCSSText += ';' +  additionalWrapperCss.join(';');
            this.wrapper.style.cssText = wrapperCSSText;

            
        }
    }

    /****************************************************************************************************
     * observer for this.windowtitle
     * updates the title of the datepicker window
     *
     ****************************************************************************************************/
    _windowTitleChanged() {
        if(this.inputWindow && this.windowtitle) {
            this.inputWindow.headertitle.innerText = this.windowtitle
        }
    }

    /**********************************************************************************************************************************************************
     * observer for this.timeformat
     * updates the input value which is the timeformat while we are in the designmode
     *
     * @memberof LasalRuntimeSigDatepicker
    ***********************************************************************************************************************************************************/
   _designModeUpdatePlacehoder(newval, oldval) {
    if (this.isdesignmode) {
        this.$["testInput"].value = this.dateformat;
    } else {
        //get date
        const date = moment(this.value, this.defaultDateFormat);
        if (date.isValid()) {
            this.$.testInput.value = this.dateformat ? date.format(this.dateformat) : date.format(this.defaultDateFormat);
        }
        else {
            this.$.testInput.value = '';
        }
        //build datepicker new cause format changed
        this._langChangeHandler();
    }
}
}
customElements.define(LasalRuntimeSigDatepickerElement.is, LasalRuntimeSigDatepickerElement);
