/*
* 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 '@polymer/paper-input/paper-input.js';
import { api_url, notificationRef } from '../../shared/constants.js';
import '@polymer/iron-dropdown/iron-dropdown.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-iconset-svg/iron-iconset-svg.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu';
import '@polymer/paper-listbox/paper-listbox';
import '@polymer/paper-item/paper-item';
import '@polymer/paper-input/paper-input';
import '../../shared-styles';
import '@vaadin/vaadin-upload/vaadin-upload';
import { GetFormattedDate ,redirectToLogin } from '../../shared/shared-script.js';

class userDashboard extends PolymerElement {
  static get template() {
    return html`
      <style include="shared-styles">
        :host {
          display: block;
        }
        #userDashboardWidget {
          font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
          border: 1px solid #4285f4;
          border-radius: 3px;
          margin-top: 10px;
          height: calc(100vh - 460px);
          min-height: 200px;
          padding: 4px 8px;
        }
        #resultPane {
          max-height: 100%;
          overflow-y: auto;
        }
        .commandSlot {
          font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
          display: flex;
          flex-wrap: wrap;
          align-items: center;
        }
        .commandVal {
            flex: 1;
            margin: 0 15px;
        }
        .sendBtn,
        .logsBtn {
            padding: 4px 8px;
            background-color: #1E88E5;
            color: #fff;
            height: 30px;
            font-size: 14px;
            margin-left: 5px;
            margin-right: 0px;
            font-weight: bold;
        }
        paper-dropdown-menu {
            --paper-dropdown-menu: {
                width : 100px;
            }
        }
        h4 {
            margin: 10px 0px;
        }
        ul {
            margin: 0px;
        }
        .mb-8 {
            margin-bottom: .5em;
        }
        a {
          text-decoration: none;
        }
      </style>
        <div>
          <div id="commandInputSlot" class="commandSlot">
            <!-- <paper-dropdown-menu always-float-label label="Module" class="searchValue" id="selectedModule">
                <paper-listbox slot="dropdown-content" class="dropdown-content" selected="1">
                    <paper-item>ALL</paper-item>
                    <template is="dom-repeat" items={{moduleLists}}>
                        <paper-item>[[item]]</paper-item>
                    </template>
                </paper-listbox>
            </paper-dropdown-menu> -->
            <paper-input id="commandInputBox" always-float-label class="commandVal" on-keyup="_userPreference" label="Command"></paper-input>
            <paper-button raised noink id="sendCommand" class="sendBtn" on-tap="_sendCommand">Execute</paper-button>
            <!-- <a href={{downloadurl}} target="_blank"><paper-button raised title="Download Log File" noink id="downloadlogs" class="logsBtn">Download</paper-button></a> -->
          </div>
          <vaadin-upload id="upload" headers={{headers}} class="vaadinUpload" id="upload" accept=".txt" target=[[url]]>
            <span slot="drop-label">Please upload .txt files</span>
          </vaadin-upload>
          <div id="userDashboardWidget">
            <div id="resultPane"></div>
          </div>
          <h4><b> Instruction : </b></h4>
          <ul>
            <li>Help - to check all commands</li>
            <li>Clear/Cls - to clearing the current window</li>
            <li>Read/Write help - to check individual commands</li>
          </ul>
        </div>
        <iron-ajax id="commandexecute" method="post" url="[[url]]" body={{livecommand}} 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}customdashboard/`
      },
      livecommand: {
        type: Object,
        value: {},
      },
      userPrefCmd: {
        type: Array,
        value: []
      },
      moduleLists: {
        type: Array,
        value: ['PS', 'PMC', 'CPM'] //, 'NPI', 'DDR'
      },
      userPrefLen: {
        type: Number,
        value: 0
      },
      downloadurl: {
        type: String,
        value: ''
      },
      headers: {
        type: Object,
        value: {}
      }
    };
  }

  _sendCommand(e) {
    const commandVal = e.currentTarget.parentNode.querySelector("paper-input").value;
    if (commandVal.trim().toLowerCase() === 'clear' || commandVal.trim().toLowerCase() === 'cls') {
      this._clearResult();
      return;
    }
    const readHelp = `<ul>
                      <li>read [hex_address,hex_address] [count] <br/>
                      <span><b> e.g. </b> </span>
                        <ul>
                            <li>read 0xfd5c0000</li>
                            <li>read 0xfd5c0000,0xf9040000</li>
                            <li>read 0xfd5c0000 5</li>
                            <li>read 0xfd5c0000,0xf9040000 5</li>
                        </ul>
                      </li>
                      <li>read [module_name.register_name,module_name.register_name] [count] <br/>
                      <span><b> e.g. </b> </span>
                        <ul>
                            <li>read *APU*</li>
                            <li>read *APU</li>
                            <li>read APU*</li>
                            <li>read APU_DUAL_CSR.ERR_CTRL</li>
                            <li>read APU_DUAL_CSR.ERR_CTRL,APU_GIC_CPUIF.GICC_CTLR</li>
                            <li>read APU_DUAL_CSR.ERR_CTRL 5</li>
                            <li>read APU_DUAL_CSR.ERR_CTRL,APU_GIC_CPUIF.GICC_CTLR 5</li>
                        </ul>
                      </li>
                    </ul>`;
    const writeHelp = `<ul>
                       <li>write [hex_address,hex_address] [hex_value] [count] <br/>
                        <span><b> e.g. </b> </span>
                          <ul>
                              <li>write 0xfd5c0000 0x1</li>
                              <li>write 0xfd5c0000,0xf9040000 0x1</li>
                              <li>write 0xfd5c0000 0x1 5</li>
                              <li>write 0xfd5c0000,0xf9040000 0x1 5</li>
                          </ul>
                       </li>
                       <li>write [module_name.register_name,module_name.register_name] [hex_value] [count] <br/>
                        <span><b> e.g. </b> </span>
                        <ul>
                            <li>write APU_DUAL_CSR.ERR_CTRL 0x1</li>
                            <li>write APU_DUAL_CSR.ERR_CTRL,APU_GIC_CPUIF.GICC_CTLR 0x1</li>
                            <li>write APU_DUAL_CSR.ERR_CTRL 0x1 5</li>
                            <li>write APU_DUAL_CSR.ERR_CTRL,APU_GIC_CPUIF.GICC_CTLR 0x1 5</li>
                        </ul>
                       </li>
                      </ul>`;
    if (commandVal.trim().toLowerCase() === 'read help') {
      this.$.resultPane.innerHTML += "<div class= " + "mb-8" + "> <b> >> " + commandVal + "</b><br/>" + readHelp;
      this._clearInput();
      return;
    } else if (commandVal.trim().toLowerCase() === 'write help') {
      this.$.resultPane.innerHTML += "<div class= " + "mb-8" + "> <b> >> " + commandVal + "</b><br/>" + writeHelp;
      this._clearInput();
      return;
    }
    else if (commandVal.trim().toLowerCase() === 'help') {
      this.$.resultPane.innerHTML += "<div class= " + "mb-8" + "> <b> >> " + commandVal + "</b><br/>" + readHelp + writeHelp;
      this._clearInput();
      return;
    }
    document.querySelector("#pageloader").style.display = "block";
    const selectOption = "am012"; //this.$.selectedModule.selectedItem.innerText.trim();
    let data = { command: '', hw_name: [] };
    if (selectOption === 'ALL')
      data.hw_name = this.moduleLists;
    else
      data.hw_name.push(selectOption);
    if (commandVal !== "") {
      data.command = commandVal;
      this.livecommand = data;
      const session = JSON.parse(localStorage.getItem('storedUser'));
      this.$.commandexecute.headers['uid'] = session.uid;
      this.$.commandexecute.headers['version'] = session.version;
      let request = this.$.commandexecute.generateRequest();
      let self = this;
      request.completes.then((req) => {
        let result = req.response;
        if (result.status === "Fail") {
          notificationRef.setAttribute('text', "Please connect to board and try again");
          notificationRef.open();
          document.querySelector("#pageloader").style.display = "none";
          document.location.reload();
          return;
        }
        if (result.error) {
          document.querySelector("#pageloader").style.display = "none";
          notificationRef.setAttribute('text', result.error);
          notificationRef.open();
          return;
        }
        if (result.data.length > 0) {
          if (self.userPrefCmd[self.userPrefCmd.length - 1] !== commandVal)
            self.userPrefCmd.push(commandVal);
          let cliresp = "<div class= " + "mb-8" + "> <b> >> " + result.command + "</b><br/>";
          _.each(result.data, (element) => {
            _.each(element.value, (ele) => {
              if (ele)
                cliresp += ele.trim() + "<br/>";
            })
          });
          cliresp += "</div>";
          self.$.resultPane.innerHTML += cliresp;
          self._clearInput();
          self.userPrefLen = self.userPrefCmd.length;
        }
        document.querySelector("#pageloader").style.display = "none";
      }, (rejected) => {
        if (request.status == 400)
        redirectToLogin();
      });
    } else {
      document.querySelector("#pageloader").style.display = "none";
      notificationRef.setAttribute('text', 'Please write a command to execute');
      notificationRef.open();
    }
  }

  _userPreference(e) {
    if (e.keyCode === 38) {
      if (this.userPrefLen - 1 >= 0) {
        this.$.commandInputBox.value = this.userPrefCmd[--this.userPrefLen];
      }
    } else if (e.keyCode === 40) {
      if (this.userPrefCmd.length > this.userPrefLen + 1) {
        this.$.commandInputBox.value = this.userPrefCmd[++this.userPrefLen]
      } else {
        this.$.commandInputBox.value = '';
        this.userPrefLen = this.userPrefCmd.length;
      }
    }
  }

  _clearInput() {
    this.$.commandInputBox.value = "";
    this.$.resultPane.scrollTop = this.$.resultPane.scrollHeight;
  }

  _executeCommand(e) {
    if (e.key === "Enter") {
      this.$.sendCommand.click();
    }
  }

  _clearResult() {
    this.$.resultPane.innerHTML = "";
    this._clearInput();
  }

  _handleErrorResponse(req) {
    document.querySelector("#pageloader").style.display = "none";
    if (_.isString(req))
      notificationRef.setAttribute('text', req);
    else if (req.detail && req.detail.error)
      notificationRef.setAttribute('text', req.detail.error);
    else
      notificationRef.setAttribute('text', 'Error: The request failed with status code: 4**');
    notificationRef.open();
  }

  ready() {
    super.ready();
    document.querySelector("#pageloader").style.display = "none";
    const session = JSON.parse(localStorage.getItem('storedUser'));
    const uid = session.uid;
    this.downloadurl = `${api_url}logfiles/${uid}/customdashboard.txt`;
    this.$.commandInputBox.addEventListener('keypress', e => this._executeCommand(e));
    this.headers["uid"] = session.uid;
    this.headers["version"] = session.version;
    const upload = this.$.upload;
    upload.addEventListener('upload-response', (event) => {
      let result = JSON.parse(event.detail.xhr.response);
      if (result.data && result.data.length > 0) {
        let cliresp = '';
        _.each(result.data, (element, i) => {
          cliresp += "<div class= " + "mb-8" + "> <b> >> " + result.data[i].command + "</b><br/>";
          if (element.value.length > 0) {
            _.each(element.value, (ele) => {
              if (ele != '') {
                cliresp += ele.trim() + "<br/>";
              }
            });
          } else
            cliresp += element.value + "<br/>";
          cliresp += "</div>";
        });
        this.$.resultPane.innerHTML += cliresp;
      }
    });
  }
}

window.customElements.define('user-dashboard', userDashboard);