/*
* 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 "../../node_modules/@polymer/polymer/polymer-element.js";
import './datatable-imports.js';
import { api_url, configObj } from "./constants.js";
import { editHex, loadLiveBitfieldsValues, writeAll, handlePaging, redirectToLogin, handleErrorResponse, _updatepaginationtext } from "./shared-script.js";

class bitfieldsTable extends PolymerElement {
  static get template() {
    return html`
        <style>
            :host {
              display: block;
            }
            paper-card {
              display: block;
              width: 100%;
              margin: auto;
              --paper-card-background-color: white;
            }
            paper-button{
              background-color: #1E88E5;
              color:white;
              height:30px;
              float:right;
              font-size:14px;
            }
            h2,.buttons {
              width: 100%;
              margin: 20px auto;
            }
            exmg-paper-toolbar .flex {
              @apply --layout-flex;
            }
            #moduleWidget,#registerWidget{
              display:none;
            }
            #moduleWidget,#registerWidget{
              margin-bottom:15px;
            }
            iron-input {
              width: 100%;
            }
            input {
              font-size: 14px;
              margin: 0px 4px;
              padding: 4px;
              border: 0px solid var(--divider-color);
              width: 100%;
            }
            exmg-paper-toolbar span.interactive-content {
              margin-left: 10px;
              white-space: nowrap;
              overflow: hidden;
              color: rgba(0,0,0,0.38);
              font-size: 14px;
              text-overflow: ellipsis;
              letter-spacing: .005em;
              box-sizing: border-box;
              font-weight: 400;
              cursor: pointer;
              width: 100%;
            }
            .search {
              background: #fff;
              box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
              0 1px 5px 0 rgba(0, 0, 0, 0.12),
              0 3px 1px -2px rgba(0, 0, 0, 0.2);
            }
            .search input {
              outline: none;
            }
            exmg-paper-datatable{
              font-size:14px;
            }
            .liveRegisterDiv {
              text-align: right;
              margin: 3px;
            }
            .text-black {
              color: #000;
            }
            paper-input {
              --paper-input-container: {
                padding: 0 !important;
              }
            }
            </style>
            <div id="titleDiv">
              <h2>
                <span>Register Bit-field Summary</span>
                <paper-button raised noink on-tap="_loadRegisters" id="backToModule"><iron-icon icon="arrow-back"></iron-icon>Back</paper-button>
                <paper-button raised noink on-tap="_loadLiveBitfieldsValues"><iron-icon icon="refresh"></iron-icon>Refresh</paper-button>
                <paper-button raised noink on-tap="_writeAll" data-key$="multiple"><iron-icon icon="create"></iron-icon>WriteAll</paper-button>
              </h2>
            </div>
            <div class="liveRegisterDiv">
              <label style="display: inline-block;" id="liveregaddress">Address : <span class="text-black">{{regAddress}}</span></label>
              <label id="liveRegisterDiv">Register Live Value : <span class="liveregistervalue">[[regliveval]]</span></label>
            </div>
            <paper-card elevation="1">
            <!-- Table Toobar -->
            <exmg-paper-toolbar>
            <div slot="default" class$="[[_computeSearchClasses(isSearch)]]">
              <template is="dom-if" if="[[isSearch]]" restamp="true">
                <iron-icon icon="exmg-paper-icons:search"></iron-icon>
                <iron-input bind-value="{{filterValue}}">
                  <input id="searchInput" placeholder="[[placeHolder]]" on-keyup="_handleKeyUp" on-blur="_handleInputBlur">
                </iron-input>
              </template>
              <template is="dom-if" if="[[!isSearch]]" restamp="true">
                <iron-icon icon="exmg-paper-icons:search"></iron-icon>
                <span class="interactive-content" on-tap="_showSearch">[[_getFilterValue(filterValue)]]</span>
              </template>
            </div>
            </exmg-paper-toolbar>
            <!-- DataTable -->
            <exmg-paper-datatable>
              <!-- THead -->
              <exmg-paper-thead sorted="{{sorted}}" sort-direction="{{sortDirection}}">
                <template>
                  <div class="tr">
                    <div title="Module Name" class="th flex-none" id="instanceName" sortable="instance_name" style="width:9%;">
                      <span>Module Name</span>
                    </div>
                    <div title="Register Name" class="th flex-none" sortable="reg_name" id="regName" style="width:9%">
                      <span>Register Name</span>
                    </div>
                    <div title="Name" class="th flex-none" sortable="name" id="bitName" style="width:12%">
                      <span>Field Name</span>
                    </div>
                    <div title="Width" class="th flex-none" sortable="width" style="width:6%">
                      <span>Bits</span>
                    </div>
                    <div title="Access Type" class="th flex-none" sortable="access_type" style="width:9%">
                      <span>Type</span>
                    </div>
                    <div title="Reset Value" class="th flex-none" sortable="reset_value" style="width:9%">
                      <span>Reset Value</span>
                    </div>
                    <div title="Description" class="th flex-none" sortable="description" id="bitDescription" style="width:21%">
                      <span>Description</span>
                    </div>
                    <div title="Live Value" class="th flex-none" sortable="liveval" style="width:10%">
                      <span>Live Value</span>
                    </div>
                    <div title="Update" class="th flex-none" sortable="update" style="width:15%">
                      <span>Update</span>
                    </div>
                  </div>
                </template>
              </exmg-paper-thead>
              <!-- TBody -->
              <exmg-paper-tbody  id="registerTableBody" items="[[items]]">
                <template>
                  <div class$="[[_computedClass(selected)]]" style="height: 100%;" aria-expand$="[[selected]]">
                    <template is="dom-if" if="[[!item.instance_name]]" restamp="true">
                      <div class="td flex-none" style$="[[_computedStyle(item.name, 20)]]">
                        <span title="[[item.name]]">[[item.name]]</span>
                      </div>
                    </template>
                    <template is="dom-if" if="[[item.instance_name]]" restamp="true">
                      <div class="td flex-none" style$="[[_computedStyle(item.name, 9, 24)]]">
                        <span title="[[item.instance_name]]">[[item.instance_name]]</span>
                      </div>
                      <div class="td flex-none regName" style$="[[_computedStyle(item.name, 9)]]">
                        <span title="[[item.reg_name]]">[[item.reg_name]]</span>
                      </div>
                      <div class="td flex-none" style$="[[_computedStyle(item.name, 12)]]">
                        <span title="[[item.name]]">[[item.name]]</span>
                      </div>
                    </template>
                    <div class="td flex-none" style$="[[_computedStyle(item.name, 6)]]">
                      <span title="[[item.width]]" class="bitWidth">[[item.width]]</span>
                    </div>
                    <div class="td flex-none" style$="[[_computedStyle(item.name, 9)]]">
                      <span title="[[item.access_type]]">[[item.access_type]]</span>
                    </div>
                    <div class="td flex-none" style$="[[_computedStyle(item.name, 9)]]">
                      <span title="[[item.reset_value]]">[[item.reset_value]]</span>
                    </div>
                    <template is="dom-if" if="[[!item.instance_name]]" restamp="true">
                      <div class="td flex-none" style$="[[_computedStyle(item.name, 31)]]">
                        <span style="white-space: normal; title="[[item.description]]">[[item.description]]</span>
                      </div>
                    </template>
                    <template is="dom-if" if="[[item.instance_name]]" restamp="true">
                      <div class="td flex-none" style$="[[_computedStyle(item.name, 21)]]">
                        <span style="white-space: normal;" title="[[item.description]]">[[item.description]]</span>
                      </div>
                    </template>
                    <div class="td flex-none" style$="[[_computedStyle(item.name, 10)]]">
                      <span class="bitliveValue"></span>
                    </div>
                    <div class="td flex-none" style$="[[_computedStyle(item.name, 15)]]">
                      <paper-input id="hexValue" no-label-float class="hexValue" auto-validate pattern="[a-fA-F0-9]*" maxlength="8" hidden$="[[_accessCheck(item.access_type)]]" style="width:70%">
                        <div slot="prefix">0X</div>
                      </paper-input>
                      <paper-icon-button icon="create" class="editBtn" on-tap="_editHex" data-reg_width$="[[item.reg_width]]" data-reg_access$="[[item.reg_access]]" data-base_address$="[[item.base_address]]" data-width$="[[item.width]]" hidden$="[[_accessCheck(item.access_type)]]" style="align-self:center;flex:1;"></paper-icon-button>
                    </div>
                  </div>
                </template>
              </exmg-paper-tbody>
            </exmg-paper-datatable>
            <!-- Table Paging -->
            <exmg-paper-paging total-items={{totalItems}} page-index="{{pageIndex}}" page-size="{{pageSize}}"></exmg-paper-paging>
          </paper-card>
          <!-- Load contacts from json file  -->
          <iron-ajax id="livevaluerefresh" method="post" url=[[getregvalurl]] body={{livevaluearray}} handle-as="json" content-type="application/json" last-response="{{handleResponse}}" on-error="_handleErrorResponse"></iron-ajax>
          <iron-ajax id="writeRegister" method="post" url=[[updateRegister]] body={{writeRegisterarray}} handle-as="json" content-type="application/json" last-response="{{handleResponse}}" on-error="_handleErrorResponse"></iron-ajax>
          <iron-ajax method="post" id="bitfieldsrequest" url=[[url]] on-response="_handleRefreshRes" body={"instance_name":"{{moduleinstanceName}}","register":"{{registername}}"} handle-as="json" content-type="application/json" last-response="{{rawItems}}" on-error="_handleErrorResponse"></iron-ajax>
          <iron-ajax method="post" id="generateTable" url={{urlSearch}} body={{searchBody}} handle-as="json" content-type="application/json" on-error="_handleErrorResponse"></iron-ajax>
          <!-- Filter items by filter value and return resulting items to the data provider  -->
          <exmg-paper-data-filter raw-items="[[rawItems]]" items="{{filteredItems}}" filter-value="[[filterValue]]" filter-fields="name"></exmg-paper-data-filter>
          <!-- Manage sorting and paging  -->
          <exmg-paper-data-helper raw-items="[[filteredItems]]" items="{{items}}" page-index="[[pageIndex]]" page-size="[[pageSize]]" sorted="[[sorted]]" sort-direction="[[sortDirection]]" total-items={{totalItems}}></exmg-paper-data-helper>
          `;
  }

  static get properties() {
    return {
      pageIndex: {
        type: Number,
        value: 0
      },
      pageSize: {
        type: Number,
        value: 100
      },
      sorted: {
        type: String,
        value: ''
      },
      sortDirection: {
        type: String,
        value: ''
      },
      filterValue: {
        type: String,
        value: ''
      },
      isSearch: {
        type: Boolean,
        value: false
      },
      placeHolder: {
        type: String,
        value: 'Search Bitfield by name'
      },
      url: {
        type: String,
        value: this.url
      },
      moduleinstanceName: {
        type: String,
        value: ''
      },
      selData: {
        type: Object,
        value: {}
      },
      livevaluearray: {
        type: Object,
        value: {
          "address": []
        }
      },
      getregvalurl: {
        type: String,
        value: api_url + 'refreshmodule/'
      },
      updateRegister: {
        type: String,
        value: api_url + 'writetoregister/'
      },
      writeRegisterarray: {
        type: Array,
        value: []
      },
      registername: {
        type: String,
        value: ''
      },
      key: {
        type: String,
        value: this.key
      },
      regliveval: {
        type: String,
        value: "-"
      },
      urlSearch: {
        type: String,
        value: ''
      },
      searchBody: {
        type: Object,
        value: ''
      },
      regAddress: {
        type: String,
        value: '',
        notify: true
      }
    };
  }

  _handleRefreshRes() {
    document.querySelector("#pageloader").style.display = "none";
  }

  _computedClass(isSelected) {
    let classes = 'tr item';

    if (isSelected) {
      classes += ' selected';
    }

    return classes;
  }

  _computedStyle(name, width, pl) {
    let customStyle = 'width:' + width + '%;height: auto;padding-top: .5em;padding-bottom: .5em;';

    if (name.toLowerCase() === 'reserved') {
      customStyle += 'background-color: #dedede;';
    }

    if (pl) customStyle += 'padding-left:' + pl + 'px;';
    return customStyle;
  }

  _accessCheck(access) {
    return access.trim() === '' || access.indexOf('w') === -1;
  }

  _editHex(e) {
    editHex(e, this);
  }

  _writeAll(e) {
    writeAll(e, this);
  }

  _loadLiveBitfieldsValues() {
    loadLiveBitfieldsValues(this, this.dataset.urlsearch && this.dataset.searchbody);
  }

  _stopTap(e) {
    e.stopPropagation();
  }

  _getFilterValue(filterValue) {
    return filterValue || this.placeHolder;
  }

  _handleKeyUp(e) {
    if (e.keyCode === 27) {
      this._hideSearch();
    }

    this.pageIndex = 0;
    let self = this;
    let eve = "";

    _updatepaginationtext(eve, self);
  }

  _handleInputBlur() {
    this._hideSearch();
  }

  _hideSearch() {
    this.set('isSearch', false);
  }

  _showSearch() {
    this.set('isSearch', true);
    setTimeout(() => this.shadowRoot.querySelector('#searchInput').focus(), 200);
  }

  _computeSearchClasses(isSearch) {
    return isSearch ? 'search' : '';
  }

  _loadRegisters(e) {
    this.parentNode.host.parentNode.parentNode.querySelector('register-table').style.display = "block";
    this.remove();
  }

  _handleErrorResponse(req) {
    handleErrorResponse(req);
  }

  ready() {
    super.ready();
    const key = this.key;
    let self = this;
    const tableHeadElement = this.shadowRoot.querySelector('exmg-paper-thead').shadowRoot;
    this.$.liveRegisterDiv.style.display = "none";

    if (this.dataset.urlsearch && this.dataset.searchbody) {
      this.$.backToModule.style.display = 'none';
      this.$.liveregaddress.style.display = "none";
      this.searchBody = this.dataset.searchbody;
      this.urlSearch = this.dataset.urlsearch;
      tableHeadElement.querySelector('#instanceName').style.display = 'flex';
      tableHeadElement.querySelector('#regName').style.display = 'flex';
      const session = JSON.parse(localStorage.getItem('storedUser'));
      self.$.generateTable.headers['uid'] = session.uid;
      self.$.generateTable.headers['version'] = session.version;
      let request = this.$.generateTable.generateRequest();
      request.completes.then(req => {
        document.querySelector("#pageloader").style.display = "none";
        const results = req.response;

        if (results.length > 0) {
          this.style.display = "block";
          let e = "";

          _updatepaginationtext(e, self);

          this.parentNode.parentNode.querySelector('#errorMsg').style.display = 'none';
        } else {
          this.style.display = "none";
          this.parentNode.parentNode.querySelector('#errorMsg').style.display = 'block';
          return;
        }

        const registerData = _.pluck(results, "registers");

        const rawItems = _.pluck(registerData, 'fields');

        results.forEach((element, i) => {
          rawItems[i].instance_name = element.instance_name;
          rawItems[i].reg_name = element.registers.name;
          rawItems[i].reg_access = element.registers.access;
          rawItems[i].reg_width = element.registers.width;
          rawItems[i].base_address = '0x' + (parseInt(element.base_address, 16) + parseInt(element.registers.address, 16)).toString(16);
        });
        self.rawItems = [...rawItems];
      }, () => {
        if (request.status == 400) redirectToLogin();
      });
    } else {
      this.registername = configObj[key].RegisterName;
      this.moduleinstanceName = configObj[key].moduleinstancename;
      this.selData = JSON.parse(this.parentNode.host.parentNode.getAttribute('selData'));
      this.regAddress = this.selData.address;
      this.livevaluearray.address = [];
      this.livevaluearray.address.push(this.selData.address);
      tableHeadElement.querySelector('#bitDescription').style.width = "31%";
      tableHeadElement.querySelector('#bitName').style.width = "20%";
      tableHeadElement.querySelector('#bitName').style.paddingLeft = "24px";
      tableHeadElement.querySelector('#instanceName').style.display = 'none';
      tableHeadElement.querySelector('#regName').style.display = 'none';
      const session = JSON.parse(localStorage.getItem('storedUser'));
      this.$.bitfieldsrequest.headers['uid'] = session.uid;
      this.$.bitfieldsrequest.headers['version'] = session.version;
      let request = this.$.bitfieldsrequest.generateRequest();
      request.completes.then(req => {
        document.querySelector("#pageloader").style.display = "none";
        let e = "";

        _updatepaginationtext(e, self);
      }, () => {
        if (request.status == 400) redirectToLogin();
      });
      this.$.titleDiv.querySelector('h2 span').innerText = configObj[key].moduleinstancename + "/" + configObj[key].RegisterName + "/Bit-Field Details";
    }

    const pagingTable = this.shadowRoot.querySelector('exmg-paper-paging').shadowRoot.querySelector('paper-dropdown-menu');
    pagingTable.addEventListener('iron-select', e => {
      handlePaging(e, this);
    });
    const paginationbtns = this.shadowRoot.querySelector('exmg-paper-paging').shadowRoot.querySelector('.page-actions').querySelectorAll('paper-icon-button');

    _.each(paginationbtns, (ele, ind) => {
      ele.addEventListener('click', e => {
        _updatepaginationtext(e, self);
      });
    });
  }

}

window.customElements.define('bitfields-table', bitfieldsTable);