/*
* Copyright (c) 2021 Xilinx, Inc.
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
* associated documentation files (the "Software"), to deal in the Software without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to 
* the following conditions: 
* 
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software. 
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* 
*
*
*/
import { PolymerElement, html } from '@polymer/polymer';
import { configObj, api_url, notificationRef } from '../../shared/constants';
import { clockTreeData, redirectToLogin, handleErrorResponse } from '../../shared/shared-script';
class TreeView extends PolymerElement {
    static get template() {
        return html`
    <style>
    :host {
        display: block;
    }
    .treeStructure {
        font-size: 14px;
        overflow-x: auto;
    }
    .treeStructure ul {
        position: relative;
        padding: 1em 0;
        white-space: nowrap;
        margin: 0 auto;
        text-align: center;
        overflow-x: hidden;
      }

      .treeStructure ul::after {
        content: '';
        display: table;
        clear: both;
      }

      .treeStructure li {
        vertical-align: top;
        text-align: center;
        list-style-type: none;
        position: relative;
        padding: 1em .5em 0 .5em;
      }

      .treeStructure li::before,
      .treeStructure li::after {
        content: '';
        position: absolute;
        top: 0;
        right: 50%;
        border-top: 1px solid #ccc;
        width: 50%;
        height: 1.1em;
      }

      .treeStructure li::after {
        right: auto;
        left: 50%;
        border-left: 1px solid #ccc;
      }

      .treeStructure li.inputRef::after,
      .treeStructure li.inputRef::before {
        display: none;
      }

      .treeStructure li.inputRef {
        padding-top: 0;
      }

      .treeStructure li:first-child::before,
      .treeStructure li:nth-last-child(2)::after {
        border: 0 none;
        border-radius: 0px !important;
      }

      .treeStructure li:nth-last-child(2)::before {
        border-right: 1px solid #ccc;
        border-radius: 0 5px 0 0;
        transform: translateX(1px);
      }

      .treeStructure li:first-child::after {
        border-radius: 5px 0 0 0;
      }

      .treeStructure ul ul::before {
        content: '';
        position: absolute;
        top: 1px;
        left: 50%;
        border-left: 1px solid #ccc;
        width: 0;
        height: 1em;
      }

      .bottomLine::after {
        content: '';
        position: absolute;
        bottom: -1em;
        left: 50%;
        border-left: 1px solid #ccc;
        width: 0;
        height: 1em;
      }

      .treeStructure .d-flex::before {
        height: 0 !important;
      }

      .treeStructure li a {
        border: 1px solid #ccc;
        padding: .5em .75em;
        text-decoration: none;
        display: inline-block;
        border-radius: 5px;
        color: #333;
        position: relative;
        top: 1px;
      }
      .freqValue {
        border-top: 1px solid;
      }
      .d-flex {
          display: flex;
          overflow-x: auto !important;
      }
      .inputRef {
          float: none !important;
          display: inline-block;
          text-align: left !important;
      }
      .inputRef::after,
      .inputRef::before {
          border: none !important;
      }
      .treePll::after,
      .treePll::before {
          border-top: none !important;
      }
      .d-block {
          display: block;
      }
      .d-inblock {
          display: inline-block;
      }
      paper-input {
          --paper-input-container: {
            width: 12em;
            padding: 0;
          }
          --paper-input-container-label: {
              font-weight: bold;
          }
      }
      .refreshBtn {
        padding: 4px 8px;
        background-color: #1E88E5;
        color: #fff;
        height: 30px;
        font-size: 14px;
        font-weight: bold;
      }
      .text-right {
        text-align: right;
      }
      .justify-center {
        justify-content: center;
      }
      .blkBgColor {
          background-color: #ddd;
          cursor: not-allowed;
      }
    </style>
    <div class="clockTree">
        <h2 class="text-right">
            <paper-button raised noink class="refreshBtn" on-tap="_refreshClock">Refresh</paper-button>
        </h2>
        <div hidden$={{!plldata.title}} class$="[[_computedClass(plldata.title)]]">
            <ul>
                <li class="inputRef">
                    <paper-input always-float-label disabled$={{plldata.npi_check}} on-blur="_onrefclkchanged" label="Ref Clock" value={{refclk}} auto-validate>
                        <div slot="suffix" style="margin-left:5px;font-size:12px;"> * {{multiplier}} &#247; {{divider}} MHz</div>
                    </paper-input>
                </li>
                <li class="treePll">
                    <a class="bottomLine">{{plldata.title}}
                        <div id='freqValue' class="freqValue">{{plldata.freq}}</div>
                    </a>
                    <ul class$="[[_computedClasses(plldata.title)]]">
                        <template is="dom-repeat" items="{{itemName}}" as='parent'>
                            <li>
                                <a>&#247; {{_itemByIndex(divisorBy, index)}}</a>
                                <ul>
                                    <template is="dom-repeat" items="{{_itemByIndex(itemName, index)}}" index-as="j" as='item'>
                                        <div>
                                            <a class$={{_computedBG(plldata.items,divisorBy,index,j)}}>{{item}}
                                                <div class="freqValue">{{_actualFreq(actFreq, index, j)}}</div>
                                            </a>
                                        </div>
                                    </template>
                                </ul>
                            </li>
                        </template>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
    <iron-ajax id="clockrefdata" method="post" body={{refclkbody}} url=[[url]] handle-as="json" on-error="_handleErrorResponse" content-type="application/json" last-response="{{lastResponse}}"></iron-ajax>
    `;
    }
    static get properties() {
        return {
            divisorBy: {
                type: String,
                value: []
            },
            itemName: {
                type: Array,
                value: []
            },
            actFreq: {
                type: String,
                value: []
            },
            url: {
                type: String,
                value: api_url + 'getclockdetails/'
            },
            plldata: {
                type: Object,
                notify: true,
                value: {},
                reflectToAttribute: true,
                observer: '_pllUpdated'
            },
            refclk: {
                type: String,
                notify: true,
                value: '',
                reflectToAttribute: true,
            },
            refclkbody: {
                type: Object,
                value: { 'refresh': false },
            },
            multiplier: {
                type: String,
                notify: true,
                value: '',
                reflectToAttribute: true,
            },
            divider: {
                type: String,
                notify: true,
                value: '',
                reflectToAttribute: true,
            }
        }
    }

    _itemByIndex(data, i) {
        return data[i];
    }

    _actualFreq(p, i, j) {
        if (p.length > 0 && p[i])
            return p[i][j];
    }

    _computedClasses(title) {
        let classes = 'd-flex';
        if (title === 'APLL')
            classes += ' justify-center';
        return classes;
    }

    _computedBG(data, divs, i, j) {
        const key = this._itemByIndex(divs, i);
        if (data[key][j].Clock_Act == 0)
            return 'blkBgColor';
        return;
    }

    _onrefclkchanged() {
        const key = this.dataset.key.toUpperCase();
        let pkey = this.dataset.pkey;
        const refclk = configObj[`${pkey}clockdata`].refclk[key.toUpperCase()].refclk;
        if (this.refclk == refclk)
            return;
        if (this.refclk === '') {
            this.refclk = refclk;
            return;
        }
        const resStatus = confirm("Altering reference clock will reflect to all PLLs.\nAre you sure?");
        if (resStatus == false) {
            this.refclk = refclk;
            return;
        }
        if(this.refclk >= 27 && this.refclk <= 60){
            document.querySelector("#pageloader").style.display = "block";
            const data = { 'refclk': this.refclk, 'refresh': false, "clock": this.dataset.pkey };
            this.refclkbody = data;
            this._commonCommands();
        }else{
            notificationRef.setAttribute('text', 'Ref clock value should be within the range 27-60MHz');
            notificationRef.open();
            this.refclk = refclk;
        }
    }

    _refreshClock() {
        let self = this;
        self.refclkbody = { 'refresh': true, "clock": this.dataset.pkey };
        document.querySelector("#pageloader").style.display = "block";
        this._commonCommands();
    }

    _commonCommands() {
        let pkey = this.dataset.pkey;
        const session = JSON.parse(localStorage.getItem('storedUser'));
        this.$.clockrefdata.headers['uid'] = session.uid;
        this.$.clockrefdata.headers['version'] = session.version;
        let request = this.$.clockrefdata.generateRequest();
        request.completes.then((req) => {
            if (req.response && req.response.status === 'Fail') {
                notificationRef.setAttribute('text', 'Please connect to board and try again');
                notificationRef.open();
                document.querySelector("#pageloader").style.display = "none";
                return;
            }
            if (req.response.error) {
                notificationRef.setAttribute('text', req.response.error);
                notificationRef.open();
                document.querySelector("#pageloader").style.display = "none";
                return;
            }
            const data = req.response.data.data;
            let ObjData = configObj[`${pkey}clockdata`];
            _.each(Object.keys(data), (key) => {
                ObjData[key] = data[key];
            });
            ObjData.refclk = req.response.data.refclk;
            const clkname = pkey;
            const refclockObj = req.response.data.refclk;
            for (let i = 0; i < ObjData.refObj.length; i++) {
                const datakey = Object.keys(ObjData.refObj[i]);
                let self = ObjData.refObj[i][datakey[0]];
                const PLL = ObjData[datakey[0].toUpperCase()];
                const ref_clk = ObjData.refclk[datakey[0].toUpperCase()].selected_pll;
                let pllupdated = configObj[datakey[0]]['plldata'];
                if (PLL) {
                    pllupdated = clockTreeData(PLL, ref_clk, refclockObj, clkname);
                    const items = pllupdated.items;
                    self.plldata.freq = pllupdated.freq;
                    self.plldata.items = items;
                    self.$.freqValue.innerHTML = self.plldata.freq;
                    if (items) {
                        let clkname = [];
                        let actualfreq = [];
                        let divby = [];
                        Object.entries(items).forEach((entry) => {
                            const [key, values] = entry;
                            clkname.push(_.pluck(values, 'Clock_Name'));
                            actualfreq.push(_.pluck(values, 'Actual_Frequency'));
                            divby.push(key);
                        });
                        self.itemName = clkname;
                        self.actFreq = actualfreq;
                        self.divisorBy = divby;
                    }
                    self.refclk = ObjData.refclk[datakey[0].toUpperCase()].refclk;
                }
            }
            let row_data = [];
            Object.entries(data).forEach((entry) => {
                const [key, values] = entry;
                values.forEach((value) => {
                    row_data.push(value);
                });
            });
            ObjData['row_data'] = row_data;
            ObjData.tableref._refreshValues();
            document.querySelector("#pageloader").style.display = "none";
        }, () => {
            if (request.status == 400)
                redirectToLogin();
        });
    }

    _pllUpdated(plldata) {
        if (plldata)
            this._pllValue(plldata.items);
    }

    _computedClass(title) {
        let classes = 'treeStructure';
        if (title === 'PPLL')
            classes += ' d-block'
        else
            classes += ' d-inblock'
        return classes;
    }

    _pllValue(items) {
        this.itemName = [];
        this.actFreq = [];
        this.divisorBy = [];
        if (items) {
            Object.entries(items).forEach((entry) => {
                const [key, values] = entry;
                this.itemName.push(_.pluck(values, 'Clock_Name'));
                this.actFreq.push(_.pluck(values, 'Actual_Frequency'));
                this.divisorBy.push(key);
            });
            return this.itemName;
        }
    }

    _handleErrorResponse(req) {
      handleErrorResponse(req);
    }

    connectedCallback() {
        super.connectedCallback();
        const key = this.dataset.key;
        let pkey = this.dataset.pkey;
        let data = {};
        data[key] = this;
        configObj['clockname'] = pkey;
        if (pkey === 'ps')
            this.url = api_url + 'getclockdetails/';
        else
            this.url = api_url + 'getmeclockdetails/';
        let ObjData = configObj[`${pkey}clockdata`];
        ObjData['refObj'].push(data);
        if (configObj[key] && configObj[key].plldata) {
            this.plldata = configObj[key].plldata;
            this.refclk = ObjData.refclk[key.toUpperCase()].refclk;
            this.multiplier = ObjData.refclk[key.toUpperCase()].multiplier;
            this.divider = ObjData.refclk[key.toUpperCase()].divider;
        }
    }
}
customElements.define('custom-tree', TreeView);