// 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';
/****************************************************************************************************
 * @class LasalRuntimeSigGroupboxTextElement
 * @extends {LasalRuntimeSigElement}
 ****************************************************************************************************/
export class LasalRuntimeSigGroupboxTextElement 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
     *
     * @readonly
     * @static
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    static get importMeta() {
        return import.meta;
    }

    /****************************************************************************************************
     * Return the component style and template as a template literal
     *
     * @readonly
     * @static
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    static get template() {
        return SigPolymer.html`
        <style include="sig-element-css">
            :host {
                /* Basic box model settings */
                display: block;
                position: absolute;
                overflow: hidden;
                font-size: 14px;

                color: var(--theme-sig-control-groupbox-text-legend-color, inherit);

                --calc-width: 2px;
                --calc-radius: 3px;                                    
            }
            
            :host * {
                /* Reset margin and paddings for child elements and turn of text selection */
                @apply --notextselect;
                margin: 0;
                padding: 0;
            }

            :host([legendonbottom]) #groupboxFieldset {
                transform: scale(1, -1);
            }

            :host([legendonbottom]) #groupboxLegend {
                transform: scale(1, -1);
            }

            .clearfix:after {
                @apply --clearfix;
            }

            .sig-control-groupbox-text {
                position: relative;
                width: 100%;
                height: 100%;
            }

            #groupboxFieldset {
                background-color: var(--theme-sig-control-groupbox-text-background-color, inherit);
                height: calc(100% + var(--theme-sig-control-groupbox-text-legend-padding-top, 0px));
                width: 100%;
                box-sizing: border-box;
                border-style: var(--theme-sig-control-groupbox-text-border-style, solid);
                border-color: var(--theme-sig-control-groupbox-text-border-color, inherit);

                border-width: var(--calc-width, 2px);
                border-radius: var(--calc-radius, 3px);

                margin-top: calc(-1 * var(--theme-sig-control-groupbox-text-legend-padding-top, 0px));
            }

            #groupboxLegend {
                white-space: nowrap;
                padding-top: calc(2 * var(--theme-sig-control-groupbox-text-legend-padding-top, 0px));
                padding-right: var(--theme-sig-control-groupbox-text-legend-padding-right, 5px);
                padding-bottom: calc(2 * var(--theme-sig-control-groupbox-text-legend-padding-bottom, 0px));
                padding-left: var(--theme-sig-control-groupbox-text-legend-padding-left, 5px);
            }
        </style>
        <div id="groupbox" class="sig-control-groupbox-text clearfix">
            <fieldset id="groupboxFieldset">
                <legend id="groupboxLegend">[[actlegendtext]]</legend>
            </fieldset>
        </div>
        `;
    }

    /****************************************************************************************************
     * define the custom tag name 
     *
     * @readonly
     * @static
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    static get is() {
        return "sig-control-groupbox-text";
    }

    /****************************************************************************************************
     * 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
     *
     * @readonly
     * @static
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    static get properties() {
        return {
            legendonbottom: {
                type: Boolean,
                value: false,
                reflectToAttribute: true,
                observer: '_updateBorderSettings'
            },
            margin: {
                type: String,
                value: '10px'
            },
            textalign: {
                type: String,
                value: 'left'
            },
            cmarginleft: {
                type: String,
                computed: '_calcMargin(textalign, margin)'
            },
            legendtext: {
                type: String,
                value: ''
            },
            value: {
                type: String,
                value: '',
                notify: true
            },
            actlegendtext: {
                type: String,
                value: ''
            },
            previewtext: {
                type: String,
                value: '-- Groupbox Text --',
            },
            texttouse: {
                type: String,
                value: 'text1'
            },
            clegendtext: {
                type: String, 
// the parameters value, text[1-3] are not used, but are necessary here for datapoint schemes to work
// without the value no text is showing and without the texts there won't be an update when the datapoint scheme switches                
                computed: '_cLegendText(legendtext, texttouse, previewtext, value, text1, text2, text3)',
                observer: '_draw'
            },
            text1: {
                txpe: String,
                value: ''
            },
            text2: {
                txpe: String,
                value: ''
            },
            text3: {
                txpe: String,
                value: ''
            }
        }
    }

    /****************************************************************************************************
     * Creates an instance of LasalRuntimeSigGroupboxTextElement.
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    constructor() {
        super();

        this.addPredefProps([{
            src: 'value',
            dest: 'text1',
            type: window.sigApi.SIG_CONST.PROP_PREDEF_PROPS_TYPE_TEXT1
        },
        {
            src: 'value',
            dest: 'text2',
            type: window.sigApi.SIG_CONST.PROP_PREDEF_PROPS_TYPE_TEXT2
        },
        {
            src: 'value',
            dest: 'text3',
            type: window.sigApi.SIG_CONST.PROP_PREDEF_PROPS_TYPE_TEXT3
        }]);
    }

    /****************************************************************************************************
     * called after property default values are set and local DOM is initialized
     *
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    ready() {
        super.ready();  
        this.isReady = true;
        if (this.isdesignmode) {
            this.propsReady = true; 
            this._updateBorderSettings();
            this._draw();
        } else {
            if (this.propsReady) {
                this._updateBorderSettings();
                this._draw();
            }  
        } 
    }

    /****************************************************************************************************
     * Gets called if required properties are ready
     *
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    sigOnRequiredPropertiesReady() {
        super.sigOnRequiredPropertiesReady();
        this.propsReady = true; 
        if (this.isReady) {
            this._updateBorderSettings();
            this._draw();
        }  
    }

    /****************************************************************************************************
     * Called when the component is resized in the designer
     * Needed when the text is aligned right, to have the correct margin
     *
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    designerOnBoundsChanged() {
        this.sigSetTimeout(() => {
            this.cmarginleft = this._calcMargin(this.textalign, this.margin);
        }, 100);
    }

    /****************************************************************************************************
     * calculate marigin and update font
     *
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    _draw() {
        this.cmarginleft = this._calcMargin(this.textalign, this.margin);
    }

    /****************************************************************************************************
    * Calculates the legend text, and sets a default if we are in designmode and there isn't one set
    * 
    * @param {String} legendtext - the text that is used for the legend
    * @param {String} textselection - the text which should be taken from the datapoint
    * @param {String} previewtext - the text which should be shown in the preview
    * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    async _cLegendText(legendtext, texttouse, previewtext) {
        let newText = "";

        if (this.isdesignmode && (!legendtext || legendtext === '')) {
            if (previewtext !== undefined) {
                newText = previewtext;
            } else {
                newText = '-- Groupbox Text --';
            }            
            this.actlegendtext = newText;
            return newText;
        }
        SigPolymer.afterNextRender(this, ()=> {
            if(this[texttouse]) {
                this.actlegendtext = this[texttouse];
            } else {
                this.actlegendtext = legendtext;
            }
        })
        
        if(this[texttouse]) {
            this.actlegendtext = this[texttouse];
            return this[texttouse]
        } else {
            this.actlegendtext = legendtext;
            return legendtext
        }        
    }

    /****************************************************************************************************
     * Margin needs to be calculated, since the legend tag doesn't really work with a right margin
     * 
     * @param {String} textalign - Defines if the text is aligned left right or center
     * @param {String} margin -The margin that the text has to the left or right border
     * @return {String} - The margin of the text
     * @memberof LasalRuntimeSigGroupboxTextElement
     ****************************************************************************************************/
    _calcMargin(textalign = 'left', margin = '0px') {
        //check if shadow dom can be accessed
        if (this.$ !== undefined) {
            let calcMargin = '0px';
            let cssMargin = margin.indexOf('px') === -1 ? margin + 'px' : margin; 
            let legendWidth = 0;
            switch (textalign) {
                case 'left':
                    calcMargin = cssMargin;
                    this.$.groupboxLegend.style.textAlign = 'left';
                    this.$.groupboxLegend.style.marginLeft = calcMargin;
                    this.$.groupboxLegend.setAttribute('align', ''); //Firefox Fix
                    break;
                case 'right':
                    legendWidth = this.$.groupboxLegend.offsetWidth;
                    calcMargin = `calc(100% - ${legendWidth}px - ${cssMargin})`;
                    this.$.groupboxLegend.style.textAlign = 'left';
                    this.$.groupboxLegend.style.marginLeft = calcMargin;
                    this.$.groupboxLegend.setAttribute('align', ''); //Firefox Fix
                    break;
                case 'center':
                    legendWidth = this.$.groupboxLegend.offsetWidth;
                    calcMargin = `0px`
                    this.$.groupboxLegend.style.textAlign = 'center';
                    this.$.groupboxLegend.style.marginLeft = calcMargin;
                    this.$.groupboxLegend.setAttribute('align', 'center'); //Firefox Fix
                    break;
                default:
            }
            return calcMargin;            
        }
    }

    /****************************************************************************************************
     * Called whenever a css prop changes
     * needed in the designmode to know when to recalculate the margin
     *
     * @param {object} cssObj an Object containing the changed CSS variables, and their values
     * @param {boolean} [doBoundsCheck=false] only relevant in designmode, leave as false
     * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    sigApplyCSSValue(cssObj, doBoundsCheck = false) {
        super.sigApplyCSSValue(cssObj, doBoundsCheck)
        if (this.isdesignmode) {
            const objKeys = Object.keys(cssObj);
            if (objKeys.length === 1 && objKeys[0].indexOf('padding') >= 0) {
                this.cmarginleft = this._calcMargin(this.textalign, this.margin);
            }
        }

        if (cssObj.hasOwnProperty('--theme-sig-control-groupbox-text-border-width')) {
            this._updateBorderSettings();
        }
        if (cssObj.hasOwnProperty('--theme-sig-control-groupbox-text-border-radius')) {
            this._updateBorderSettings();
        }
    }

    /****************************************************************************************************
    * Called whenever the orientation changes via legendonbottom
    * needed to update shorthand border settings accordingly
    *
    * @memberof LasalRuntimeSigGroupboxTextElement
    ****************************************************************************************************/
    _updateBorderSettings() {
        if ((this.propsReady) && (this.isReady)) {
            let borderWidth = this.style.getPropertyValue('--theme-' + this.tagName.toLowerCase() + '-border-width');
            let borderRadius = this.style.getPropertyValue('--theme-' + this.tagName.toLowerCase() + '-border-radius');

            if (this.legendonbottom === false) {
                // not flipped => use the original settings directly
                this.updateStyles({
                    '--calc-width'   : borderWidth,
                    '--calc-radius'  : borderRadius,
                });
            } else {
                // change bottom and top settings
                this._getBorderSettings(borderWidth, borderRadius);

                let newWidth;
                if ((borderWidth === "") || (borderWidth === undefined)) {
                    // in this case the default value is applied
                    newWidth = "";
                } else {
                    newWidth = `${this.borderBottomWidth}px ${this.borderRightWidth}px ${this.borderTopWidth}px ${this.borderLeftWidth}px`;
                }

                let newRadius;
                if ((borderRadius === "") || (borderRadius === undefined)) {
                    // in this case the default value is applied
                    newRadius = "";
                } else {
                    newRadius = `${this.borderBottomLeftRadius}px ${this.borderBottomRightRadius}px ${this.borderTopRightRadius}px ${this.borderTopLeftRadius}px`;
                }

                this.updateStyles({
                    '--calc-width'   : newWidth,
                    '--calc-radius'  : newRadius,
                });
            }
        }
    }

    /****************************************************************************************************
    * Method to get all the border width elements independent of the used shorthand style
    * @memberof LasalRuntimeSigOutputElement
    ****************************************************************************************************/
    _getBorderSettings(borderWidth, borderRadius) {
        if (borderWidth === "") {
            this.borderTopWidth = this.borderRightWidth = this.borderBottomWidth = this.borderLeftWidth = 0;            
        } else {
            let values = borderWidth.split(' ');
        
            switch (values.length) {
                case 1: // "5px"
                    this.borderTopWidth = this.borderRightWidth = this.borderBottomWidth = this.borderLeftWidth = parseInt(values[0]);
                    break;
                case 2: // "1px 5px"
                    this.borderTopWidth = this.borderBottomWidth = parseInt(values[0]);
                    this.borderRightWidth = this.borderLeftWidth = parseInt(values[1]);
                    break;
                case 3: // "1px 5px 10px"
                    this.borderTopWidth = parseInt(values[0]);
                    this.borderRightWidth = this.borderLeftWidth = parseInt(values[1]);
                    this.borderBottomWidth = parseInt(values[2]);
                    break;
                case 4: // "1px 5px 10px 15px"
                    this.borderTopWidth = parseInt(values[0]);
                    this.borderRightWidth = parseInt(values[1]);
                    this.borderBottomWidth = parseInt(values[2]);
                    this.borderLeftWidth = parseInt(values[3]);
                    break;
                default: // invalid format => use no border
                    this.borderTopWidth = this.borderRightWidth = this.borderBottomWidth = this.borderLeftWidth = 0;
                    break;
            }
        }

        if (borderRadius === "") {
            this.borderTopLeftRadius = this.borderTopRightRadius =
            this.borderBottomLeftRadius = this.borderBottomRightRadius = 0;
          } else {
            let values = borderRadius.split(' ');
        
            switch (values.length) {
                case 1: // "5px"
                this.borderTopLeftRadius = this.borderTopRightRadius = this.borderBottomRightRadius = this.borderBottomLeftRadius = parseInt(values[0]);
                break;
            case 2: // "5px 10px"
                this.borderTopLeftRadius = this.borderBottomRightRadius = parseInt(values[0]);
                this.borderTopRightRadius = this.borderBottomLeftRadius = parseInt(values[1]);
                break;
            case 3: // "5px 10px 15px"
                this.borderTopLeftRadius = parseInt(values[0]);
                this.borderTopRightRadius = this.borderBottomLeftRadius = parseInt(values[1]);
                this.borderBottomRightRadius = parseInt(values[2]);
                break;
            case 4: // "5px 10px 15px 20px"
                this.borderTopLeftRadius = parseInt(values[0]);
                this.borderTopRightRadius = parseInt(values[1]);
                this.borderBottomRightRadius = parseInt(values[2]);
                this.borderBottomLeftRadius = parseInt(values[3]);
                break;
            default: // invalid format => use no radius
                this.borderTopLeftRadius = this.borderTopRightRadius = this.borderBottomRightRadius = this.borderBottomLeftRadius  = 0;
                break;
            }
        }
    }          
}
customElements.define(LasalRuntimeSigGroupboxTextElement.is, LasalRuntimeSigGroupboxTextElement);
