/*
* 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 { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { api_url, notificationRef, socket_url, configObj } from '../../../shared/constants.js';
import '@polymer/paper-dialog/paper-dialog.js';
import './user_graph';
import '../../../shared-styles';
import { GetFormattedDate, redirectToLogin, handleErrorResponse } from '../../../shared/shared-script.js';
class userPerformance extends PolymerElement {
  static get template() {
    return html`
      <style include="shared-styles">
        :host {
          display: block;
        }
        .sendBtn,
        .closeBtn,
        .logsBtn {
          padding: 4px 8px;
          background-color: #1E88E5;
          color: #fff;
          height: 30px;
          font-size: 14px;
          font-weight: bold;
          text-align: center;
          float: right;
          margin-top: 1.2em;
        }
        paper-dropdown-menu {
          --paper-dropdown-menu: {
            width : 100px;
          }
        }
        .configcol:nth-child(odd) {
          margin-right: 15px;
        }
        .card {
          margin: 10px 0;
        }
        .d-flex {
          display: flex;
          flex-wrap: wrap;
        }
        .configcol {
          width: calc(50% - 40px);
        }
        .hide {
          display: none;
        }
        .dropmenu::after{
          content: '';
          display: block;
          clear: both;
        }
      </style>
        <div>
          <div class="dropmenu">
            <paper-dropdown-menu always-float-label label="Number of Plot" on-iron-select="_selectedPlot" id="selectedModule">
              <paper-listbox slot="dropdown-content" class="dropdown-content" selected="0">
                <template is="dom-repeat" items={{plotLists}}>
                  <paper-item>[[item]]</paper-item>
                </template>
              </paper-listbox>
            </paper-dropdown-menu>
            <iron-icon icon="info-outline" id="loadInstructions" slot="item-icon" style="color:#ee3626;"></iron-icon>
            <paper-button raised noink id="generateplot" class="sendBtn" on-tap="_configPlot">Generate</paper-button>
            <paper-button raised noink id="closebtn" class="closeBtn" on-tap="_closePlot">Close</paper-button>
            <!-- <a href={{downloadurl}} target="_blank"><paper-button raised title="Download Log File" noink id="downloadlogs" class="logsBtn">Download</paper-button></a> -->
          </div>
          <div class="d-flex" id="userplotconfig">
            <template is="dom-repeat" items={{plotItems}} as="item">
              <div class="card configcol" data-items$={{item}} data-index$={{index}}>
                <!-- <iron-icon icon="icons:close" slot="item-icon" class="closeIcon hide" on-tap="_closePlot"></iron-icon> -->
                <div class="configbox">
                  <!-- <paper-dropdown-menu always-float-label label="Module" value={{item.hw_name}}>
                    <paper-listbox slot="dropdown-content" class="dropdown-content" selected="6">
                      <template is="dom-repeat" items={{moduleLists}}>
                        <paper-item>[[item]]</paper-item>
                      </template>
                    </paper-listbox>
                  </paper-dropdown-menu> -->
                  <paper-input name="name" label="Module_Name.Register_Name/Address" class="combination" required auto-validate always-float-label value={{item.name}}></paper-input>
                  <paper-input name="displayname" label="Display Name" always-float-label value={{item.displayname}}></paper-input>
                  <paper-input name="legend" label="Legend" always-float-label value={{item.legend}}></paper-input>
                  <paper-input name="y_axis" label="Y-axis" always-float-label value={{item.y_axis}}></paper-input>
                </div>
                <div class="graph_sec hide">
                  <user-graph id="{{currentUser}}{{index}}" key="{{currentUser}}{{index}}"></user-graph>
                </div>
              </div>
            </template>
           </div>
            <paper-dialog id="instructionmodal">
              <div class="m-0 p-0 h-100">
                <div class="instructionBoard">
                  <ul>
                    <li>Either Address or Module, Module Name and Register Name are mandatory</li>
                    <li>Display Name will be the Chart Title</li>
                    <li>Legend is the name of parameter plotting on the chart</li>
                    <li>Y-axis : Measuring unit of the legend</li>
                  </ul>
                </div>
              </div>
            </paper-dialog>
          </div>
          <iron-ajax id="configplot" method="post" url="[[url]]" body={{configData}} handle-as="json" content-type="application/json" last-response="{{handleResponse}}" on-error="_handleErrorResponse"></iron-ajax>
          <iron-ajax id="closeplot" method="post" url="[[closeurl]]" body={{closeData}} handle-as="json" content-type="application/json" last-response="{{handleResponse}}" on-error="_handleErrorResponse"></iron-ajax>
      `;
  }
  static get properties() {
    return {
      url: {
        type: String,
        value: `${api_url}configureplot/`
      },
      closeurl: {
        type: String,
        value: `${api_url}closeplot/`
      },
      plotLists: {
        type: Array,
        value: [0, 1, 2, 3, 4, 5, 6, 7, 8]
      },
      plotItems: {
        type: Array,
        value: []
      },
      configData: {
        type: Array,
        value: []
      },
      closeData: {
        type: Array,
        value: []
      },
      moduleLists: {
        type: Array,
        value: [  'PS', 'PMC', 'CPM']
      },
      refObjects: {
        type: Array,
        value: []
      },
      downloadurl: {
        type: String,
        value: ''
      },
      threadarray: {
        type: Array,
        value: []
      },
      currentUser: {
        type: String,
        value: 'user'
      }
    };
  }

  _selectedPlot(e) {
    const selected = e.target.selectedItem.innerText.trim();
    this.$.closebtn.style.display = "none";
    if (parseInt(selected))
      this.$.generateplot.style.display = "block";
    else
      this.$.generateplot.style.display = "none";
    this.plotItems = [];
    for (let i = 0; i < parseInt(selected); i++)
      this.plotItems.push({ 'threadname': this.currentUser + i, 'y_axis': 'value', 'hw_name': 'am012', 'name': '', 'tab': 'plot', 'uid': this.currentUser, 'key': 'plot' });
  }

  _closePlot() {
    let self = this;
    const bodyData = _.map(self.plotItems, ele => _.pick(ele, 'threadname'));
    self.closeData = bodyData;
    const card = self.$.userplotconfig.querySelectorAll('.configcol')
    document.querySelector("#pageloader").style.display = "block";
    self.$.closeplot.headers['uid'] = self.currentUser;
    let request = self.$.closeplot.generateRequest();
    request.completes.then((req) => {
      const result = req.response;
      document.querySelector("#pageloader").style.display = "none";
      if (result.status === 'Fail') {
        notificationRef.setAttribute('text', "Please connect to board and try again");
        notificationRef.open();
        document.location.reload();
        return;
      }
      if (result.error) {
        notificationRef.setAttribute('text', result.error);
        notificationRef.open();
        return;
      }
      self.closePlot = false;
      self.plotItems = [];
      self.$.selectedModule.querySelector("paper-listbox").selected = 0;
      self.$.generateplot.style.display = "block";
      self.$.closebtn.style.display = "none";
      self.$.selectedModule.style.display = "inline-block";
      self.$.loadInstructions.style.display = "inline-block";
      _.each(card, (element) => {
        element.querySelector('.graph_sec').classList.add('hide');
        element.querySelector('.configbox').classList.remove('hide');
      });
      self.ws.close();
    }, () => {
      if (request.status == 400)
        redirectToLogin();
    });
  }

  _configPlot() {
    let index = -1;
    let data = {};
    let self = this;
    let flag = 0;
    if (MyAppGlobals.boardstatus) {
      const cards = self.$.userplotconfig.querySelectorAll('.configcol');
      self.configData = [];
      cards.forEach((ele) => {
        index = ele.dataset.index;
        data = JSON.parse(ele.dataset.items);
        ele.querySelector('.combination').validate();
        if (!data.name)
          flag = 1;
        if (_.includes(data.name, '.')) {
          const keys = data.name.split('.');
          if (keys.length == 2) {
            _.each(keys, (item) => {
              if (!item)
                flag = 1;
            });
          } else
            flag = 1;
        } else if (data.name.indexOf('0x') > -1) {
          data.address = data.name;
          data.name = '';
        } else
          flag = 1;
        if (flag)
          return;
        if (data.legend === '')
          if (data.name)
            data.legend = data.name.replace('.', '_');
          else
            data.legend = data.address;
        const userID = this.currentUser + index;
        let title = 'Address';
        if (data.displayname)
          title = data.displayname;
        else if (data.name)
          title = data.name;
        configObj[userID] = {};
        configObj[userID] = { 'title': title, 'y_axis': data.y_axis, 'legend': data.legend };
        const pData = _.pick(data, _.identity);
        self.configData.push(pData);
      });
      if (flag) {
        notificationRef.setAttribute('text', "Please provide correct value");
        notificationRef.open();
        return;
      }
      document.querySelector("#pageloader").style.display = "block";
      self.$.configplot.headers['uid'] = self.currentUser;
      const session = JSON.parse(localStorage.getItem('storedUser'));
      self.$.configplot.headers['version'] = session.version;
      let request = self.$.configplot.generateRequest();
      request.completes.then((req) => {
        const result = req.response;
        if (result.status === 'Fail') {
          document.querySelector("#pageloader").style.display = "none";
          notificationRef.setAttribute('text', "Please connect to board and try again");
          notificationRef.open();
          document.location.reload();
          return;
        }
        if (result.error) {
          document.querySelector("#pageloader").style.display = "none";
          notificationRef.setAttribute('text', result.error);
          notificationRef.open();
          return;
        }
        self._loadwsdata(result.response);
        //document.querySelector("#pageloader").style.display = "none";
      }, () => {
        if (request.status == 400)
          redirectToLogin();
      });
    } else {
      document.querySelector("#pageloader").style.display = "none";
      notificationRef.setAttribute('text', "Please Connect to board and try again");
      notificationRef.open();
      document.location.reload();
    }
  }

  async _loadwsdata(res) {
    let self = this;
    const keyref = 'userPlot';
    const tab_name = 'plot';
    configObj[keyref] = '';
    self.$.generateplot.style.display = "none";
    self.$.closebtn.style.display = "block";
    self.$.selectedModule.style.display = "none";
    self.$.loadInstructions.style.display = "none";
    const threadname = _.pluck(res, 'threadname');
    const thread_createtime = _.pluck(res, 'thread_createtime');
    let threadsarr = [];
    _.each(threadname, (ele, ind) => {
      let threadObj = {};
      threadObj["threadname"] = ele;
      threadObj["thread_createtime"] = thread_createtime[ind];
      threadsarr.push(threadObj);
    });
    self.threadarray = threadsarr;
    await self._updateObjects();
    if ("WebSocket" in window) {
      let ws = new WebSocket(`ws://${socket_url}/ws`);
      self.ws = ws;
      const session = JSON.parse(localStorage.getItem('storedUser'));
      self.closePlot = true;
      ws.onopen = () => {
        ws.send(JSON.stringify({"tab": tab_name, "uid": session["uid"], "threads": threadsarr}));
      };
      ws.onmessage = (evt) => {
        self._websocketreceiver(ws, evt, session, tab_name, keyref, threadname, thread_createtime, threadsarr);
      };
    } else {
      notificationRef.setAttribute('text', "WebSocket NOT supported by your Browser!");
      notificationRef.open();
    }
    //document.querySelector("#pageloader").style.display = "none";
  }

  async _websocketreceiver(ws, evt, session, tab_name, keyref, threadname, thread_createtime) {
    let self = this;
    const datum = JSON.parse(evt.data);
    for (let i=0; i<datum.length; i++) {
      const data = datum[i];
      if (data.tabname === `${tab_name}_${session.uid}`) {
        if (data.error && document.location.pathname === '/usertab') {
          notificationRef.setAttribute('text', data.error);
          notificationRef.open();
        } else
          notificationRef.close();
        if (data.data.length > 0) {
          await self._generateData(datum, i);
        }else{
          self.threadarray[i]["time"] = data.time;
        }
      }
    }
    if (self.closePlot) {
      ws.send(JSON.stringify({"tab":tab_name,"uid":session["uid"], "threads": self.threadarray}));
    }
  }

  async _updateObjects() {
    let self = this;
    self.refObjects = [];
    const userBlocks = self.$.userplotconfig.querySelectorAll('.configcol');
    for (let i = 0; i < userBlocks.length; i++) {
      userBlocks[i].querySelector('.graph_sec').classList.toggle('hide');
      userBlocks[i].querySelector('.configbox').classList.toggle('hide');
      self.refObjects.push({
        "ref": userBlocks[i].querySelector('#' + this.currentUser + i),
        key: this.currentUser + i
      });
    }
  }

  _handleErrorResponse(req) {
    handleErrorResponse(req);
  }

  async _generateData(jsondata, ind) {
    let self = this;
    // const userBlocks = self.$.userplotconfig.querySelectorAll('.configcol');
    // for (let i = 0; i < userBlocks.length; i++) {
      let refObj = _.findWhere(self.refObjects, {
        key: this.currentUser + ind
      });
      let refdata = _.findWhere(jsondata, {
        threadname: this.currentUser + ind
      });
      let reftime = _.findWhere(jsondata, {
        threadname: this.currentUser + ind
      });
      self.threadarray[ind]["time"] = reftime.time;
      if (refdata && refdata.data && refObj)
        await refObj.ref._updatedUserGraph(refdata.data, refObj.key);
    // }
  }

  ready() {
    super.ready();
    let self = this;
    document.querySelector("#pageloader").style.display = "none";
    const session = JSON.parse(localStorage.getItem('storedUser'));
    const uid = session.uid;
    this.downloadurl = `${api_url}logfiles/${uid}/plot.txt`;
    this.$.loadInstructions.addEventListener('mouseover', () => {
      self.$.instructionmodal.open();
    });
    this.$.loadInstructions.addEventListener('mouseleave', () => {
      self.$.instructionmodal.close();
    });
  }

  connectedCallback() {
    super.connectedCallback();
    const session = JSON.parse(localStorage.getItem('storedUser'));
    this.currentUser = session.uid;
  }

}
window.customElements.define('user-performance', userPerformance);