<!-- eslint-disable -->
<template>
  <v-container fluid class="api-client grid-list-xs pa-0" style="height: 100%">
    <splitpanes style="height: 100%" class="xc-theme">
      <pane min-size="20" max-size="50" size="30" style="overflow: auto">
        <!--        <p class="body-2 my-1 text-center grey&#45;&#45;text text&#45;&#45;lighten-1" v-show="!isDashboard">-->
        <!--          {..} REST API CLIENT</p>-->
        <v-row class="pa-0 ma-0 pa-2 pl-2">
          <div class="cursor-pointer d-flex" style="width: 100%">
            <x-icon
              v-ge="['api-client', 'open-new-collection']"
              icon-class="mr-1 cursor-pointer"
              small
              color="primary"
              tooltip="Create New API Collection"
              @click="openNewCollection('/')"
            >
              mdi-folder-plus-outline
            </x-icon>

            <!--            <x-icon class="mr-1" color="primary" tooltip="Open API Collection" @click="openApiFileCollection">-->
            <!--              mdi-folder-open-outline-->
            <!--            </x-icon>-->
            <v-dialog v-model="importCollection.modal" persistent max-width="550">
              <template #activator="{ on }">
                <v-icon color="" v-on="on"> mdi-import </v-icon>
              </template>
              <v-card class="pa-3" style="position: relative">
                <v-icon
                  v-ge="['api-client', 'open-new-collection-close']"
                  style="position: absolute; right: 20px; top: 20px"
                  @click="importCollection.modal = false"
                >
                  mdi-close
                </v-icon>

                <v-card-title class="headline justify-center mb-2"> Import </v-card-title>
                <v-card-subtitle class="text-center"> (JSON Format Only) </v-card-subtitle>

                <div style="" class="py-3">
                  <v-card-text>
                    <v-select
                      v-model="importCollection.type"
                      dense
                      hide-details
                      outlined
                      :items="importCollection.types"
                      filled
                      label="API Specification"
                    />
                  </v-card-text>
                  <v-card-actions>
                    <v-tabs background-color="indigo accent-4" dark style="border: 1px solid indigo; margin: 0 10px">
                      <v-tab>FILE</v-tab>
                      <v-tab :disabled="!isSwaggerImport"> URL </v-tab>
                      <v-tab :disabled="!isSwaggerImport"> JSON </v-tab>
                      <v-tab-item>
                        <div class="px-2 py-10 text-center" style="min-height: 250px">
                          <v-row>
                            <v-col>
                              <v-text-field
                                v-model="importCollection.file.srcFilePath"
                                hide-details
                                label="Select file"
                                dense
                                outlined
                              >
                                <template #append>
                                  <v-btn v-ge="['api-client', 'select-import-file']" small @click="selectImportFile()">
                                    Choose File ...
                                  </v-btn>
                                </template>
                              </v-text-field>
                            </v-col>
                          </v-row>

                          <v-row v-show="isSwaggerImport">
                            <v-col>
                              <v-text-field
                                v-model="importCollection.file.dstFilePath"
                                hide-details
                                label="Destination file path"
                                dense
                                outlined
                                hide-details
                              />
                            </v-col>
                          </v-row>

                          <v-btn
                            v-ge="['api-client', 'import-collection']"
                            class="mt-4"
                            color="primary"
                            @click="
                              importFile(
                                importCollection.type,
                                importCollection.file.srcFilePath,
                                importCollection.file.dstFilePath
                              )
                            "
                          >
                            Import
                          </v-btn>
                        </div>
                      </v-tab-item>
                      <v-tab-item>
                        <div style="min-height: 250px" class="text-center">
                          <div class="px-2 pt-10">
                            <v-text-field v-model="importCollection.url" placeholder="Enter url" />
                          </div>

                          <v-btn
                            v-ge="['api-client', 'import-collection-from-url']"
                            color="primary"
                            @click="importFromUrl(importCollection.type, importCollection.url)"
                          >
                            Import
                          </v-btn>
                        </div>
                      </v-tab-item>
                      <v-tab-item>
                        <div style="min-height: 250px" class="text-center">
                          <div class="px-2 pt-2">
                            <v-textarea v-model="importCollection.text" placeholder="Enter JSON String" />
                          </div>
                          <v-btn
                            v-ge="['api-client', 'import-collection-from-text']"
                            color="primary"
                            @click="importFromText(importCollection.type, importCollection.text)"
                          >
                            Import
                          </v-btn>
                        </div>
                      </v-tab-item>
                    </v-tabs>
                  </v-card-actions>
                </div>
              </v-card>
            </v-dialog>
            <v-spacer />
            <span v-show="!isDashboard" class="flex-shrink-1 body-2 my-1 text-center grey--text">
              {..} REST API CLIENT ( is in <v-icon small color="warning">mdi-alpha</v-icon>)</span
            >

            <span v-show="isDashboard" class="caption float-right warning--text mt-1" style="font-style: italic">
              API Client is in<v-icon small color="warning">mdi-alpha</v-icon>
            </span>
          </div>
        </v-row>
        <v-divider />

        <v-tabs v-model="apiRootTab" height="32" style="border-top: 1px solid darkgrey">
          <v-tab style="text-transform: none"> History </v-tab>
          <v-tab style="text-transform: none"> Collections </v-tab>

          <v-tab-item style="border-top: 1px solid grey">
            <div class="apis-list">
              <div v-for="(api, i) in historyList" :key="i" class="pa-0 ma-0">
                <v-list-item v-ge="['api-client', 'history']" dense two-line @click="apiClickedOnHistoryList(api)">
                  <v-hover v-slot="{ hover }">
                    <v-list-item-content>
                      <v-list-item-title class="grey--text">
                        <v-btn
                          class="pl-0 ml-0"
                          small
                          text
                          :tooltip="api.meta.path"
                          :color="apiMethodMeta[api.meta.method.toUpperCase()].color"
                        >
                          <b>
                            <v-icon
                              class="mx-0 ml-n2"
                              :class="{
                                'white--text': !api.meta.response || !api.meta.response.status,
                                'red--text': api.meta.response && api.meta.response.status >= 400,
                                'green--text': api.meta.response && api.meta.response.status < 400,
                              }"
                            >
                              mdi-circle-small
                            </v-icon>
                            {{ api.meta.method }}
                          </b>
                        </v-btn>

                        {{ api.meta.path }}
                      </v-list-item-title>
                      <v-list-item-subtitle v-show="!i || hover" class="text-right">
                        <span v-show="!i && !hover" class="grey--text text--darken-1 caption">(Last invoked API) </span>

                        <v-icon v-if="_isDev" v-ge="['api-client', 'node-info']" small @click.stop="showNodeInfo(api)">
                          mdi-information
                        </v-icon>
                        <v-btn
                          v-show="hover"
                          v-ge="['api-client', 'delete-list']"
                          small
                          text
                          class=" "
                          @click="apiDeleteFromList(i)"
                        >
                          <v-icon small> mdi-delete </v-icon>
                        </v-btn>
                      </v-list-item-subtitle>
                    </v-list-item-content>
                  </v-hover>
                </v-list-item>
                <v-divider />
              </div>
            </div>
          </v-tab-item>
          <v-tab-item style="border-top: 1px solid grey">
            <v-expansion-panels v-model="curApiCollectionPanel" accordion focusable>
              <v-expansion-panel v-for="(apiTv, i) in apiTvs" :key="i">
                <v-expansion-panel-header hide-actions>
                  <template #default="{ open }">
                    <div class="d-flex">
                      <v-icon color="">
                        {{ open ? 'mdi-menu-down' : 'mdi-menu-right' }}
                      </v-icon>
                      <v-icon small color="grey" class="ml-1 mr-2"> mdi-folder </v-icon>

                      <span class="body-2 flex-grow-1">{{
                        $store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][i].fileName
                      }}</span>

                      <x-icon
                        color="white grey"
                        class="float-right mr-3"
                        small
                        @click="(showCtxMenu[i] = true), (x = $event.clientX), (y = $event.clientY)"
                        @click.stop=""
                      >
                        mdi-dots-horizontal
                      </x-icon>

                      <recursive-menu
                        v-model="showCtxMenu[i]"
                        v-ge="['api-client', 'collection-context-menu']"
                        :position-x="x"
                        :position-y="y"
                        :items="{
                          'Add Folder': 'add-folder',
                          'Add Request': 'add-request',
                          'Reveal in Folder': 'reveal-in-folder',
                          'Delete Collection': 'delete-collection',
                          'Refresh Collection': 'refresh-collection',
                        }"
                        @click="ctxMenuClickHandler($event, i)"
                      />
                    </div>
                  </template>
                </v-expansion-panel-header>
                <v-expansion-panel-content class="expansion-wrap-0 pl-4">
                  <vue-tree-list
                    v-if="apiTvs[i]"
                    style="cursor: pointer"
                    class="body-2 sql-query-treeview px-1 pt-2 api-treeview"
                    :model="apiTv"
                    default-tree-node-name="new node"
                    default-leaf-node-name="new leaf"
                    :default-expanded="false"
                    @click="tvNodeOnClick"
                    @change-name="tvNodeRename"
                    @delete-node="tvNodeDelete"
                    @add-node="onAddNode"
                  >
                    <span slot="leafNodeIcon" />
                    <v-icon slot="treeNodeIcon" small color="grey" class="mr-1"> mdi-folder-star </v-icon>

                    <v-icon slot="addTreeNode" small> mdi-folder-plus </v-icon>
                    <v-icon slot="addLeafNode" small> mdi-file-plus </v-icon>
                    <v-icon slot="editNode" small class="mt-n1"> mdi-file-edit </v-icon>
                    <v-icon slot="delNode" small> mdi-delete </v-icon>
                    <template #label="{ item: api }">
                      <div
                        v-if="api.isLeaf"
                        class="d-flex pa-1 ma-n1"
                        style="width: 100%"
                        :style="
                          api.id === currentApi.id && !currentApi.meta.history ? 'background:rgb(240, 240, 240)' : ''
                        "
                      >
                        <!--                    <v-icon class="mx-0"-->
                        <!--                            :class="`${apiMeta[api.method].color}&#45;&#45;text`"-->
                        <!--                            small>-->
                        <!--                              mdi-bookmark-outline-->
                        <!--                            </v-icon>-->
                        <span
                          style="display: inline-block; min-width: 45px"
                          :class="
                            apiMethodMeta[api.meta.method.toUpperCase()]
                              ? `${apiMethodMeta[api.meta.method.toUpperCase()].color}--text`
                              : ''
                          "
                        >
                          {{ api.meta.method.toUpperCase() === 'DELETE' ? 'DEL' : api.meta.method.toUpperCase() }}
                        </span>

                        <span
                          class="grey--text d-block text--darken-1"
                          style="text-overflow: ellipsis; overflow: hidden; white-space: nowrap"
                          >{{ api.name }}</span
                        >
                        <v-spacer />
                        <v-icon v-if="_isDev" v-ge="['api-client', 'node-info']" small @click.stop="showNodeInfo(api)">
                          mdi-information
                        </v-icon>
                      </div>
                      <div
                        v-else
                        class="d-flex"
                        style="width: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap"
                      >
                        <span>{{ api.name }}</span>

                        <v-spacer />
                        <v-icon v-if="_isDev" v-ge="['api-client', 'node-info']" small @click.stop="showNodeInfo(api)">
                          mdi-information
                        </v-icon>
                      </div>
                    </template>
                  </vue-tree-list>
                </v-expansion-panel-content>
              </v-expansion-panel>
            </v-expansion-panels>
          </v-tab-item>
        </v-tabs>
      </pane>
      <pane min-size="10" size="70" style="overflow: auto">
        <v-toolbar
          class="toolbar-border-bottom elevation-0 d-flex req-inputs"
          height="55"
          style="position: relative; z-index: 2; width: 100%"
        >
          <v-select
            v-model="api.method"
            v-ge="['api-client', 'method']"
            :items="Object.keys(apiMethodMeta)"
            dense
            solo
            hide-details
            outlined
            class="body-2"
            style="
              max-width: 130px;
              border-bottom-right-radius: 0;
              border-top-right-radius: 0;
              border-right: 1px solid grey;
            "
          />

          <xAutoComplete
            v-model="api.path"
            outlined
            class="flex-grow-1"
            :env="selectedEnv"
            placeholder="Enter HTTP URL"
            solo
            dense
            hide-details
            autofocus
            styles="border-bottom-left-radius: 0;border-top-left-radius:0 "
          />

          <x-btn
            v-ge="['api-client', 'api-send']"
            btn.class="primary"
            dense
            tooltip="Send Request"
            @click.prevent="apiSend()"
          >
            <v-icon v-if="isPerfFilled" small class="ml-n3"> mdi-truck-fast </v-icon>
            <v-icon v-else small class="ml-n3"> mdi-send </v-icon>
            &nbsp;SEND
          </x-btn>
          <x-btn
            v-ge="['api-client', 'save']"
            btn.class="outlined"
            dense
            :icon="api.history ? 'save' : 'mdi-content-save-edit'"
            tooltip="Save API"
            @click.prevent="saveOrUpdateApi(api)"
          />
          <x-btn
            v-ge="['api-client', 'environment']"
            icon="mdi-eye-outline"
            tooltip="Environments"
            @click="environmentDialog = true"
          />
        </v-toolbar>

        <splitpanes horizontal style="height: calc(100% - 64px)" class="xc-theme">
          <pane min-size="25" size="50" style="overflow: auto" class="pa-1">
            <v-tabs class="req-tabs" height="24">
              <v-tab v-ge="['api-client', 'params']" class="caption">
                Params&nbsp;<b v-if="paramsCount" class="green--text">({{ paramsCount }})</b>
              </v-tab>
              <v-tab v-ge="['api-client', 'headers']" class="caption">
                Headers&nbsp;<b v-if="headersCount" class="green--text">({{ headersCount }})</b>
              </v-tab>
              <v-tab v-ge="['api-client', 'body']" class="caption"> Body </v-tab>
              <v-tab v-ge="['api-client', 'auth']" class="caption"> Auth </v-tab>
              <v-tab v-ge="['api-client', 'perf-test']" class="caption"> Perf Test </v-tab>
              <div class="flex-grow-1 d-flex text-right pr-4 justify-end">
                <div class="flex-shrink-1">
                  <v-select
                    v-model="selectedEnv"
                    height="19"
                    class="caption envs"
                    dense
                    :items="environmentList"
                    placeholder="Environment"
                    single-line
                  >
                    <template #selection="{ item }">
                      <span style="text-transform: uppercase">{{ item }}</span
                      >&nbsp; <span class="grey--text">(env)</span>
                    </template>
                  </v-select>
                </div>
              </div>
              <!--              <div class="flex-grow-1 text-right pr-4 caption" v-if="api.response">-->
              <!--                &lt;!&ndash;                <x-icon iconClass="mr-4"  v-if="$store.getters['project/GtrProjectJson']" @click="environmentDialog = true" tooltip="Environments">&ndash;&gt;-->
              <!--                &lt;!&ndash;                  mdi-eye-outline&ndash;&gt;-->
              <!--                &lt;!&ndash;                </x-icon>&ndash;&gt;-->
              <!--              </div>-->
              <v-tab-item>
                <params v-model="api.parameters" :env.sync="selectedEnv" />
              </v-tab-item>
              <v-tab-item>
                <headers v-model="api.headers" :env.sync="selectedEnv" />
              </v-tab-item>
              <v-tab-item>
                <monaco-json-editor
                  v-model="api.body"
                  style="height: 250px"
                  class="editor card"
                  theme="vs-dark"
                  lang="json"
                  :options="{ validate: true, documentFormattingEdits: true, foldingRanges: true }"
                />
              </v-tab-item>
              <v-tab-item>
                <!--                <monaco-editor-->
                <!--                  :code.sync="api.auth"-->
                <!--                  cssStyle="height:250px"></monaco-editor>-->
              </v-tab-item>

              <v-tab-item>
                <perf-test v-model="api.perf" />
              </v-tab-item>
            </v-tabs>
          </pane>
          <pane min-size="25" size="50" style="overflow: auto" class="pa-1">
            <!--            <h3 class="mb-2 grey&#45;&#45;text lighten-1">-->
            <!--              Response Body :-->
            <!--              <div v-if="api.response">-->
            <!--                <span v-if="api.response.status === 200" class="green&#45;&#45;text">{{api.response.status}}</span>-->
            <!--                <span v-if="api.response.status !== 200" class="red&#45;&#45;text">{{api.response.status}}</span>-->
            <!--              </div>-->
            <!--            </h3>-->

            <v-tabs v-if="api.response" height="24">
              <v-tab v-ge="['api-client', 'response-body']" class="caption"> Body </v-tab>
              <v-tab v-ge="['api-client', 'respomse-headers']" class="caption">
                Headers<span v-if="api.response.headers" class="green--text"
                  >( {{ Object.keys(api.response.headers).length }} )</span
                >
              </v-tab>
              <div v-if="api.response" class="flex-grow-1 text-right pr-4 caption">
                <template v-if="api.response.status">
                  <span class="grey--text">Status:</span
                  ><span
                    :class="{
                      'green--text': api.response.status === 200,
                      'red--text': api.response.status !== 200,
                    }"
                    ><b>{{ api.response.status }}</b></span
                  >
                </template>
                &nbsp; &nbsp;
                <template v-if="api.timeTaken">
                  <span class="grey--text">Time:</span
                  ><span class="green--text"
                    ><b>{{ api.timeTaken }}ms</b></span
                  >
                </template>
              </div>
              <v-tab-item>
                <pre
                  v-if="api.response"
                  class="black pa-1 grey--text w-100 caption"
                  style="overflow-x: auto; min-height: 100px; overflow-y: auto; min-width: 100%"
                  >{{ api.response.data }}</pre
                >

                <!--                <pre v-if="api.response" class="black pa-1" style="overflow-x: auto;min-height:50px;overflow-y:auto">{{api.response.data}}</pre>-->
              </v-tab-item>
              <v-tab-item>
                <pre
                  v-if="api.response"
                  class="black pa-1 grey--text w-100 caption"
                  style="overflow-x: auto; min-height: 100px; overflow-y: auto; min-width: 100%"
                  >{{ api.response.headers }}</pre
                >
              </v-tab-item>
            </v-tabs>
          </pane>
        </splitpanes>
      </pane>
    </splitpanes>
    <environment v-model="environmentDialog" env="_noco" />

    <v-dialog v-model="bookmarkApiDialog" max-width="500">
      <v-card>
        <v-card-title class="justify-center"> Bookmark API </v-card-title>

        <v-card-text>
          <div class="text-right">
            <v-btn
              v-ge="['api-client', 'open-new-collection']"
              small
              color="primary"
              outlined
              @click="openNewCollection('/')"
            >
              <v-icon small> mdi-plus </v-icon> &nbsp;New Collection
            </v-btn>
          </div>
          <v-list dense>
            <v-list-item-group v-model="choosenApiCollection">
              <v-list-item
                v-for="(item, i) in $store.getters['apiClientSwagger/GtrCurrentApiFilePaths']"
                :key="i"
                :value="i"
                style="border: 1px solid grey"
              >
                <v-list-item-title>{{ item.fileName }}</v-list-item-title>
              </v-list-item>
            </v-list-item-group>
          </v-list>
        </v-card-text>
        <v-card-actions class="justify-center pb-5">
          <v-btn v-ge="['api-client', 'bookmark']" small @click="bookmarkApiDialog = false">
            <!-- Cancel -->
            {{ $t('general.cancel') }}
          </v-btn>
          <v-btn
            small
            color="primary"
            :disabled="choosenApiCollection === null || choosenApiCollection === undefined"
            @click="bookmarkApi(choosenApiCollection)"
          >
            Save API
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-container>
</template>
<script>
/* eslint-disable */

import { mapGetters } from 'vuex';

import Vue from 'vue';

import { VueTreeList, Tree, TreeNode } from 'vue-tree-list';
import { Splitpanes, Pane } from 'splitpanes';
import params from '../apiClient/Params';
import headers from '../apiClient/Headers';

import { MonacoJsonEditor } from '../monaco/index';

import environment from '../Environment';
import PerfTest from '../apiClient/PerfTest';

// const {app, dialog, path, fs, shell, XcApis} = require("electron").remote.require(
//   "./libs"
// );

import * as XcApiHelp from '../../helpers/XcApiHelp';

// const {config} = require('electron').remote.require('./libs');

export default {
  components: {
    PerfTest,
    MonacoJsonEditor,
    VueTreeList,
    Splitpanes,
    Pane,
    params,
    headers,
    environment,
  },
  data() {
    return {
      choosenApiCollection: null,
      bookmarkApiDialog: false,
      apiRootTab: 0,
      importCollection: {
        modal: false,
        type: 'Swagger 3.0',
        types: [
          {
            text: 'Swagger 3.0',
            value: 'Swagger 3.0',
          },
          {
            text: 'XC',
            value: 'XC',
          },
        ],
        file: {
          srcFilePath: '',
          dstFilePath: '',
        },
      },
      fileHistory: null,
      historyList: [],
      environmentDialog: false,
      showCtxMenu: {},
      apiTvs: [],
      apiFilePaths: [],
      apiFileCollections: [],
      curApiCollectionPanel: null,

      x: 0,
      y: 0,

      apiMethodMeta: {
        GET: {
          color: 'success',
        },
        POST: {
          color: 'warning',
        },
        DELETE: {
          color: 'error',
        },
        PUT: {
          color: 'info',
        },
        HEAD: {
          color: 'info',
        },
        PATCH: {
          color: 'info',
        },
      },

      // current api
      api: {
        method: 'GET',
        path: '',
        body: '',
        params: [],
        auth: '',
        headers: [],
        response: {},
        perf: {},
        meta: {},
      },
      currentApi: {},
      currentNode: null,
    };
  },
  computed: {
    isPerfFilled() {
      return this.api.perf && Object.values(this.api.perf).some(v => v);
    },
    ...mapGetters({
      sqlMgr: 'sqlMgr/sqlMgr',
      currentProjectFolder: 'project/currentProjectFolder',
      projectApisFolderPath: 'project/projectApisFolderPath',
      projectApisFolder: 'project/projectApisFolder',
    }),
    isSwaggerImport() {
      return this.importCollection.type === 'Swagger 3.0';
    },
    paramsCount() {
      return this.api.parameters && this.api.parameters.filter(p => p.name && p.enabled).length;
    },
    headersCount() {
      return this.api.headers && this.api.headers.filter(h => h.name && h.enabled).length;
    },
    environmentList() {
      if (this.isDashboard) {
        return Object.keys(this.$store.getters['project/GtrApiEnvironment']);
      } else {
        return Object.keys(this.$store.getters['project/GtrDefaultApiEnvironment']);
      }
    },
    selectedEnv: {
      get() {
        return (
          this.$store.state.apiClientSwagger.activeEnvironment[this.$store.state.apiClientSwagger.currentProjectKey] ||
          this.environmentList[0]
        );
      },
      set(env) {
        this.$store.commit('apiClientSwagger/MutActiveEnvironment', { env });
      },
    },
  },
  watch: {
    async historyList(newData) {
      await this.fileHistory.write({
        path: config.electron.apiHistoryPath,
        data: newData,
      });
    },
  },

  async created() {
    try {
      /* load history collection - default path is within app directory */
      await this.loadHistoryFile();

      if (this.$route.params && this.$route.params.project) {
        /* get collection paths previously opened for this project */
        this.$store.dispatch('apiClientSwagger/loadApiCollectionForProject', {
          projectId: this.$route.params.project,
          projectName: this.$store.getters['project/GtrProjectName'],
        });
      } else {
        /* get collection paths previously opened */
        this.$store.dispatch('apiClientSwagger/loadApiCollectionForProject', {});
      }

      /* load the filecollection json as treeviews */
      for (let i = 0; i < this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'].length; ++i) {
        await this.loadFileCollection(this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][i]);
      }
    } catch (e) {
      console.log('Failed to load previously opened query collections', e);
    }

    if (this.nodes && this.nodes.url) {
      Vue.set(this.api, 'method', 'GET');
      this.api.path = this.nodes.url;
    }

    this.api.meta = {};

    try {
      const info = (
        await this.$axios.get('/nc/projectApiInfo', {
          headers: {
            'xc-auth': this.$store.state.users.token,
          },
        })
      ).data;
      const rest = Object.values(info).find(v => v.apiUrl);
      if (rest) {
        Vue.set(this.api, 'method', 'GET');
        Vue.set(this.api, 'path', rest.apiUrl);
      }
    } catch (e) {}
  },
  mounted() {},
  beforeDestroy() {},
  methods: {
    showNodeInfo(api) {
      console.log('Node info : ', api);
    },
    async handleKeyDown({ metaKey, key, altKey, shiftKey, ctrlKey }) {
      // cmd + s -> save
      // cmd + l -> reload
      // cmd + n -> new
      // cmd + d -> delete
      // cmd + enter -> send api

      switch ([metaKey, key].join('_')) {
        case 'true_s':
          await this.bookmarkApi();
          break;
        case 'true_e':
          this.environmentDialog = true;
          break;
        // case 'true_n' :
        //   this.addColumn();
        //   break;
        case 'true_d':
          await this.deleteProcedure('showDialog');
          break;
        case 'true_Enter':
          await this.apiSend();
          break;
      }
    },

    async openCollectionFolder(pathString) {
      shell.showItemInFolder(pathString);
    },
    async openNewCollection() {
      try {
        const toLocalPath = this.isDashboard
          ? path.join(this.currentProjectFolder, 'server', 'tool', this.projectApisFolder)
          : '';

        const userChosenPath = dialog.showSaveDialog({
          defaultPath: toLocalPath,
          filters: [{ name: 'JSON', extensions: ['json'] }],
        });

        if (userChosenPath) {
          fs.writeFileSync(userChosenPath, '[]', 'utf-8');
          const pathObj = {
            path: userChosenPath,
            fileName: path.basename(userChosenPath),
          };
          this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
          await this.loadFileCollection(pathObj);
        }
        this.$toast.success('New API collection loaded successfully').goAway(5000);
      } catch (e) {
        console.log(e);
        throw e;
      }
    },
    async openSwaggerJSONFile(srcPath, dstPath) {
      const dstFileName = path.basename(dstPath);
      await XC.importSwaggerJson({
        srcPath,
        dstPath,
      });
      const pathObj = {
        path: dstPath,
        fileName: dstFileName,
      };
      this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
      await this.loadFileCollection(pathObj);
    },
    selectImportFile() {
      const file = dialog.showOpenDialog({
        properties: ['openFile'],
      });

      const dstFileName = `${path.basename(file[0], '.json')}.xc.json`;

      let dstPath = '';
      if (this.isDashboard) {
        dstPath = this.projectApisFolderPath;
      } else {
        dstPath = path.dirname(config.electron.apiHistoryPath);
      }

      if (file && file[0]) {
        this.$set(this.importCollection.file, 'srcFilePath', file[0] + '');
        this.$set(this.importCollection.file, 'dstFilePath', path.join(dstPath, dstFileName));
      }
    },
    async importFile(type, srcPath, dstPath) {
      this.apiRootTab = 1;
      this.$set(this.importCollection, 'modal', false);
      try {
        if (type === 'Swagger 3.0') {
          await this.openSwaggerJSONFile(srcPath, dstPath);
        } else {
          await this.openApiFileCollection(srcPath, dstPath);
        }
        this.$toast.success('File imported successfully').goAway(3000);
      } catch (e) {
        console.log('File import error : ', e);
        this.$toast.error('File importing failed').goAway(3000);
      }
    },
    async importFromUrl(type, url) {
      this.apiRootTab = 1;
      this.$set(this.importCollection, 'modal', false);
      try {
        if (type === 'Swagger 3.0') {
          await this.importSwaggerFromUrl(url);
        } else {
          await this.importXcFromUrl(url);
        }
        this.$toast.success('Import from URL completed successfully').goAway(3000);
      } catch (e) {
        console.log('URL import error : ', e);
        this.$toast.error('Import from URL failed').goAway(3000);
      }
    },
    async importFromText(type, text) {
      this.apiRootTab = 1;
      this.$set(this.importCollection, 'modal', false);
      try {
        if (type === 'Swagger 3.0') {
          await this.importSwaggerFromText(text);
        } else {
          await this.importXcFromText(text);
        }
        this.$toast.success('Import from Text completed successfully').goAway(3000);
      } catch (e) {
        console.log('Text import error : ', e);
        this.$toast.error('Import from Text failed').goAway(3000);
      }
    },

    async importSwaggerFromUrl(url) {
      const data = await this.$axios.$get(url);

      const dstFileName = `${Date.now()}.xc.json`;

      let dstPath = '';
      if (this.isDashboard) {
        dstPath = this.projectApisFolderPath;
      } else {
        dstPath = path.dirname(config.electron.apiHistoryPath);
      }

      await XC.importSwaggerObject({
        swagger: data,
        dstPath: path.join(dstPath, dstFileName),
      });

      const pathObj = {
        path: path.join(dstPath, dstFileName),
        fileName: dstFileName,
      };

      this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
      await this.loadFileCollection(pathObj);
    },
    async importSwaggerFromText(text) {
      const data = JSON.parse(text);

      const dstFileName = `${Date.now()}.xc.json`;

      let dstPath = '';
      if (this.isDashboard) {
        dstPath = this.projectApisFolderPath;
      } else {
        dstPath = path.dirname(config.electron.apiHistoryPath);
      }

      await XC.importSwaggerObject({
        swagger: data,
        dstPath: path.join(dstPath, dstFileName),
      });

      const pathObj = {
        path: path.join(dstPath, dstFileName),
        fileName: dstFileName,
      };

      this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
      await this.loadFileCollection(pathObj);

      this.$toast.success('Import from Text completed successfully').goAway(3000);
    },
    async importXcFromUrl(url) {
      const data = await this.$axios.$get(url);

      const dstFileName = `${Date.now()}.xc.json`;

      let dstPath = '';
      if (this.isDashboard) {
        dstPath = this.projectApisFolderPath;
      } else {
        dstPath = path.dirname(config.electron.apiHistoryPath);
      }

      // await XcApis.importSwaggerObject({
      //   swagger: data,
      //   dstPath: path.join(dstPath, dstFileName)
      // })

      const pathObj = {
        path: path.join(dstPath, dstFileName),
        fileName: dstFileName,
      };

      this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
      await this.loadFileCollection(pathObj);
    },
    async importXcFromText(text) {
      const data = JSON.parse(text);

      const dstFileName = `${Date.now()}.xc.json`;

      let dstPath = '';
      if (this.isDashboard) {
        dstPath = this.projectApisFolderPath;
      } else {
        dstPath = path.dirname(config.electron.apiHistoryPath);
      }
      //
      // await XcApis.importSwaggerObject({
      //   swagger: data,
      //   dstPath: path.join(dstPath, dstFileName)
      // })

      const pathObj = {
        path: path.join(dstPath, dstFileName),
        fileName: dstFileName,
      };

      this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
      await this.loadFileCollection(pathObj);

      this.$toast.success('Import from Text completed successfully').goAway(3000);
    },

    async ctxMenuClickHandler(actionEvent, index) {
      switch (actionEvent.value) {
        case 'add-folder':
          this.tvNodeFolderAdd(index);
          break;
        case 'add-request':
          this.curApiCollectionPanel = index;
          this.tvNodeRequestAdd(index);
          break;
        case 'reveal-in-folder':
          await this.openCollectionFolder(this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][index].path);
          break;
        case 'delete-collection':
          this.$store.commit('apiClientSwagger/MutApiFilePathsRemove', index);
          this.apiFileCollections.splice(index, 1);
          this.apiTvs.splice(index, 1);
          break;
        case 'refresh-collection':
          await this.refreshFileCollection(index);
          break;
        default:
          break;
      }
      // this.deleteQueryByPath(this.apiTvs, this.menuItem.path);
    },
    openUrl(url) {
      shell.openExternal(url);
    },

    apiClickedOnList(api) {
      if (api.isLeaf) {
        api = XcApiHelp.apiPrepareForInvocation(api);

        this.currentApi = JSON.parse(JSON.stringify(api));
        this.api = {
          perf: {},
          ...this.currentApi.meta,
        };
      }
    },

    apiClickedOnHistoryList(api) {
      this.currentApi = JSON.parse(JSON.stringify(api));
      this.api = {
        perf: {},
        ...api.meta,
        history: true,
        isLeaf: true,
      };
    },

    apiDeleteFromList(index) {
      this.$store.commit('apiClientSwagger/MutListRemove', index);
    },

    async apiSend() {
      if (!this.api.path.trim()) {
        this.$toast.info('Please enter http url').goAway(3000);
        return;
      }

      const envs = this.isDashboard
        ? this.$store.getters['project/GtrApiEnvironment'][this.selectedEnv]
        : this.$store.getters['project/GtrDefaultApiEnvironment'][this.selectedEnv];

      const apiDecoded = JSON.parse(
        JSON.stringify(this.api).replace(/{{\s*(\w+)\s*}}/g, (m, m1) => {
          if (m1 in envs) {
            return envs[m1];
          } else {
            this.$toast.info('Environment variable is not found : ' + m1).goAway(3000);
            return m;
          }
        })
      );

      const swaggerResult = await this.$store.dispatch('apiClientSwagger/send', { api: this.api, apiDecoded });

      this.historyList = [{ ...this.currentApi, meta: swaggerResult, pid: 0 }, ...this.historyList];

      const result = swaggerResult.response;
      this.api = swaggerResult;

      if (result) {
        if (result.status === 200) {
          // this.$toast.success('API invoked successfully',{duration:1000});
        } else {
          this.$toast.error(`Error:${result.status}`, { duration: 1000 });
        }
      } else {
        this.$toast.error('Some internal error occurred', { duration: 1000 });
      }
    },

    async fileCollectionReload() {
      const data = new Tree(await this.apiFileCollection.read());

      this.apiTv = data;
      // this.$set(this, 'apiCollections', data);
    },

    async tvNodeDelete(node) {
      console.log(node, this.curApiCollectionPanel);
      node.remove();
      await this.savefileCollections(this.curApiCollectionPanel);
    },

    async tvNodeRename(params) {
      await this.savefileCollections(this.curApiCollectionPanel);
    },

    async onAddNode(params) {
      await this.savefileCollections(this.curApiCollectionPanel);
    },

    async tvNodeOnClick(node) {
      const { parent, children, ...params } = node;
      this.currentNode = node;

      this.apiClickedOnList(params);
      // if (params.query) ;
      // this.selectQuery(params)
    },

    async savefileCollections(index = 0) {
      await this.apiFileCollections[index].write({ data: this.tvToObject(index) });
      // this.apiTvs = await this.fileCollections.read();
      // this.$set(this.apiTvs, index, this.apiTvs);
    },

    tvToObject(index) {
      try {
        const vm = this;

        function _dfs(oldNode) {
          const newNode = {};

          XcApiHelp.nodeHandleIfNew(oldNode);

          for (const k in oldNode) {
            if (k !== 'children' && k !== 'parent') {
              newNode[k] = oldNode[k];
            }
          }

          if (oldNode.children && oldNode.children.length > 0) {
            newNode.children = [];
            for (let i = 0, len = oldNode.children.length; i < len; i++) {
              newNode.children.push(_dfs(oldNode.children[i]));
            }
          }

          return newNode;
        }

        return _dfs(vm.apiTvs[index]).children;
      } catch (e) {
        this.$toast.error('Error while parsing api collection').goAway(3000);
      }
    },

    async tvNodeFolderAdd(index) {
      const node = new TreeNode({ name: 'New Folder', isLeaf: false, children: [] });
      if (!this.apiTvs[index].children) {
        this.apiTvs[index].children = [];
      }
      this.apiTvs[index].addChildren(node);

      await this.saveFileCollection(index);
    },
    async tvNodeRequestAdd(index) {
      const node = new TreeNode({ name: 'New Request', isLeaf: true });
      if (!this.apiTvs[index].children) {
        this.apiTvs[index].children = [];
      }
      this.apiTvs[index].addChildren(node);

      await this.saveFileCollection(index);
    },

    openApiFileCollection(filePath = null) {
      const vm = this;
      // console.log(obj, key);

      const file = filePath
        ? [filePath]
        : dialog.showOpenDialog({
            properties: ['openFile'],
          });

      if (file && file[0]) {
        const fileName = path.basename(file[0]);
        const pathObj = {
          path: file[0] + '',
          fileName,
        };

        if (this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'].every(({ path: p }) => p !== pathObj.path)) {
          this.$store.commit('apiClientSwagger/MutApiFilePathsAdd', pathObj);
          this.loadFileCollection(pathObj);
        } else {
          this.$toast.info('File already exist in collection').goAway(4000);
        }
      }
    },

    async saveFileCollection(index = 0) {
      await this.apiFileCollections[index].write({ data: this.tvToObject(index) });
    },

    async loadFileCollection(path, index = 0) {
      try {
        /* create file collection and get its data */
        const fileCollection = new XC(path);
        await fileCollection.init();
        this.apiFileCollections.push(fileCollection);
        const treeData = await fileCollection.read();

        /* create a tree view and push it */
        const data = new Tree(treeData.length && treeData[0].name === 'swagger.json' ? treeData[0].children : treeData);
        this.apiTvs.push(data);

        this.curApiCollectionPanel = this.apiFileCollections.length - 1;
      } catch (e) {
        console.log('Error in loadFileCollection:', e);
        throw e;
      }
    },
    async loadHistoryFile() {
      // try {
      //   this.fileHistory = new XcApis({path: config.electron.apiHistoryPath});
      //   this.historyList = await this.fileHistory.read();
      // } catch (e) {
      //   console.log('Error in loadFileHistory:', e);
      //   throw e;
      // }
    },
    async refreshFileCollection(index = 0) {
      try {
        const path = this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][index];
        const fileCollection = new XC(path);
        await fileCollection.init();
        this.apiFileCollections[index] = fileCollection;
        const data = new Tree(await fileCollection.read());
        this.$set(this.apiTvs, index, data);
      } catch (e) {
        console.log('Error in loadFileCollection:', e);
        throw e;
      }
    },

    async bookmarkApi(panelIndex) {
      this.bookmarkApiDialog = false;
      if (this.apiFileCollections.length) {
        delete this.currentApi.meta.history;
        const q = this.currentApi;
        const node = new TreeNode({
          name: q.meta.path,
          swagger: {},
          isLeaf: true,
          id: Date.now(),
          pid: 0,
          ...q,
        });

        if (!this.apiTvs[panelIndex].children) {
          this.apiTvs[panelIndex].children = [];
        }
        this.apiTvs[panelIndex].addChildren(node);
        await this.savefileCollections(panelIndex);
        await this.refreshFileCollection(panelIndex);

        this.$toast
          .success(
            `API added to ${this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][panelIndex].fileName} collection successfully`
          )
          .goAway(3000);
      } else {
        this.$toast.info('Create a new collection to bookmark the api.').goAway(3000);
        this.openNewCollection('/');
      }
    },
    async saveOrUpdateApi() {
      if (this.api.history) {
        this.bookmarkApiDialog = true;
      } else {
        const q = this.currentApi;
        const api = {
          ...q,
          meta: { ...this.api },
          pid: 0,
        };
        const activePanelIndex = this.curApiCollectionPanel;
        await this.apiFileCollections[activePanelIndex].updateApi({ api });
        await this.refreshFileCollection(activePanelIndex);
        this.$toast
          .success(
            `API updated in ${this.$store.getters['apiClientSwagger/GtrCurrentApiFilePaths'][activePanelIndex].fileName} collection successfully`
          )
          .goAway(3000);
      }
    },
  },

  beforeCreated() {},
  destroy() {},
  directives: {},
  validate({ params }) {
    return true;
  },
  head() {
    return {};
  },
  props: ['nodes'],
};
</script>

<style scoped>
.apis-list {
  height: calc(100%);
  overflow-y: auto;
}

.apis-request {
  overflow-y: auto;
}

/deep/ > .req-inputs .v-toolbar__content {
  width: 100%;
  display: flex;
  padding: 2px;
}

/deep/ .req-tabs > .v-tabs-items {
  border-top: 1px solid #7f828b33;
}

.envs /deep/ .v-select__selections {
  color: var(--v-accent-base);
}

/*.envs /deep/ .v-select__selections input { display: none}*/
code {
  min-height: 200px;
}
</style>

<!--
/**
 * @copyright Copyright (c) 2021, Xgene Cloud Ltd
 *
 * @author Naveen MR <oof1lab@gmail.com>
 * @author Pranav C Balan <pranavxc@gmail.com>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
-->