<template>
  <el-popover
    v-model="visible"
    class="address-select-wrap"
    :width="width"
    :visible-arrow="false"
    :popper-options="popoverOptions"
    placement="bottom-start"
    popper-class="address-select-popover"
    transition="el-zoom-in-top"
    @click.stop
    @show="onShow"
    @hide="onHide"
    @after-leave="onLeave"
  >
    <el-tabs
      v-model="current"
      v-loading="loading"
      class="address-tab"
      type="border-card"
      @tab-click="handleClick"
    >
      <div class="search-area">
        <el-input
          ref="searchInput"
          v-model="searchKey"
          prefix-icon="el-icon-search"
          :placeholder="searchPlaceholder"
          class="search-ipt popper-ipt"
          size="small"
          @input="onSearch"
          @keydown.native="mouseMove($event)"
        />
      </div>
      <el-tab-pane name="prov" label="省份">
        <el-scrollbar class="list-area">
          <div
            v-for="(item, index) in list.prov"
            :key="index"
            class="address-item"
            :class="value[0] === item.name ? 'current': ''"
            @click="handleSelectProv(item)"
          >{{ item.name }}</div>
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane name="city" label="城市">
        <el-scrollbar class="list-area">
          <div
            v-for="(item, index) in list.city"
            :key="index"
            class="address-item"
            :class="value[1] === item.name ? 'current': ''"
            @click="handleSelectCity(item)"
          >{{ item.name }}</div>
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane name="area" label="区域">
        <el-scrollbar class="list-area">
          <div
            v-for="(item, index) in list.area"
            :key="index"
            class="address-item"
            :class="value[2] === item.name ? 'current': ''"
            @click="handleSelectArea(item)"
          >{{ item.name }}</div>
        </el-scrollbar>
      </el-tab-pane>
    </el-tabs>
    <div slot="reference" class="trigger-area">
      <el-input
        ref="address-ipt"
        v-model="address"
        readonly
        size="small"
        :placeholder="placeholder"
        @focus="onFocus"
        @blur="onBlur"
      />
      <i class="flag-icon el-icon-arrow-down" :class="isFocus ? 'rotate-arrow' : ''" />
    </div>
  </el-popover>
</template>

<script>
import { on, off } from "../utils/dom.js";
import { debounce } from "throttle-debounce";
import { addClass, removeClass } from "../utils/index";
import Axios from "axios";
import { getToken } from "../utils/auth";

export default {
  name: "Address",
  props: {
    placeholder: {
      type: String,
      default: ""
    },
    value: {
      type: [Array, String, Number],
      default() {}
    },
    country: {
      type: String,
      default: "CHN"
    },
    // 是否监听元素变化自动定位弹出框
    autoPosition: {
      type: Boolean,
      default: true
    },
    // 接口的完整路径
    url: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      isFirst: true,
      visible: false,
      searchKey: "",
      current: "prov",
      loading: false,
      list: {
        prov: [],
        city: [],
        area: []
      },
      original: {
        prov: [],
        city: [],
        area: []
      },
      selectionOptions: {
        prov: "",
        city: "",
        area: ""
      },
      address: "",
      debouncedGetData: "",
      width: "300px",
      isFocus: false,
      triggerLock: {},
      popoverOptions: {},
      offsetTr: 30,
      currentLine: 0
    };
  },
  computed: {
    searchPlaceholder() {
      let key = "";
      if (this.current === "prov") key = "省份";
      else if (this.current === "city") key = "城市";
      else if (this.current === "area") key = "区域";
      return `请输入${key}`;
    }
  },
  watch: {
    value: {
      handler(n, o) {
        let address = "";
        n.forEach(e => {
          address += `${e.name}/`;
        });
        this.address = address.slice(0, address.length - 1);
        !n.length && (this.address = "");
      },
      immediate: true
    }
  },
  mounted() {
    this.init();
    this.autoPosition && this.handleAddInputObserver();
  },
  destroyed() {
    const that = this;
    off(window, "resize", that.debouncedResize);
  },
  methods: {
    onHide() {
      if (this.value.length < 3 || typeof this.value[1] === "undefined") {
        this.reset();
      }
    },
    onLeave() {
      const $trigger = document.querySelectorAll(".trigger-area");
      for (let i = 0; i < $trigger.length; i++) {
        sessionStorage.setItem(`lock${i}`, "false");
      }
    },
    reset() {
      this.$emit("input", []);
      this.address = "";
      this.current = "prov";
      this.list.city = [];
      this.list.area = [];
    },
    onShow() {
      this.searchKey = "";
      this.resizePopover();
      this.visible = true;
      this.$nextTick(function() {
        this.$refs.searchInput.$el
          .getElementsByClassName("el-input__inner")[0]
          .focus();
      });
      this.$nextTick(() => {
        this.current = "prov";
        this.list.city = [];
        this.list.area = [];
        this.getSsq("prov");
      });
    },
    mouseMove(event) {
      const wrap = document.querySelectorAll(".list-area");
      const allList = document.querySelectorAll(".address-item");
      let index;
      if (this.current === "prov") index = 0;
      else if (this.current === "city") index = 1;
      else if (this.current === "area") index = 2;
      const scrollWrap = wrap[index].querySelector(".el-scrollbar__wrap");
      // const scrollBody = wrap.querySelector('.el-scrollbar__view')
      const listItem = wrap[index].querySelectorAll(".address-item");
      if (event.keyCode === 38) {
        this.offsetTr = 0;
        this.currentLine--;
        this.changeItem(listItem, scrollWrap);
      } else if (event.keyCode === 40) {
        this.offsetTr = 24;
        this.currentLine++;
        this.changeItem(listItem, scrollWrap);
      } else if (event.keyCode === 13 && this.currentLine > -1) {
        if (this.current === "prov") {
          this.handleSelectProv(this.list.prov[this.currentLine - 1]);
        } else if (this.current === "city") {
          this.handleSelectCity(this.list.city[this.currentLine - 1]);
        } else if (this.current === "area") {
          this.handleSelectArea(this.list.area[this.currentLine - 1]);
        }
        this.currentLine = 0;
        this.changeBackground(allList);
      }
    },
    changeItem: function(listItem, scrollWrap) {
      this.changeBackground(listItem);
      if (this.currentLine < 1) this.currentLine = listItem.length;
      if (this.currentLine > listItem.length) this.currentLine = 1;
      // removeClass(listItem[this.currentLine - 1], 'noselectColor')
      addClass(listItem[this.currentLine - 1], "selectColor");
      scrollWrap.scrollTop =
        listItem[this.currentLine - 1].offsetTop - this.offsetTr;
    },
    changeBackground: function(listItem) {
      for (var i = 0; i < listItem.length; i++) {
        removeClass(listItem[i], "selectColor");
        // addClass(listItem[i], 'noselectColor')
      }
    },
    onFocus() {
      this.isFocus = true;
    },
    onBlur() {
      this.isFocus = false;
    },
    init() {
      const that = this;
      this.debouncedGetData = debounce(100, this.handleSearch);
      this.debouncedResize = debounce(200, this.resizePopover);
      that.debouncedResize();
      on(window, "resize", that.debouncedResize);
    },
    onSearch() {
      this.debouncedGetData();
    },
    handleClick(tab, event) {
      // console.log(this.searchKey)
    },
    resizePopover() {
      let result = "";
      const $input = this.$refs["address-ipt"];
      result = $input ? $input.$el.offsetWidth : 300;
      this.width = result;
    },
    handleSelectProv(item) {
      this.selectionOptions.prov = item;
      this.$emit("input", [item]);
      this.address = `${this.selectionOptions.prov.name}`;
      this.current = "city";
      this.searchKey = "";
      this.$nextTick(() => {
        this.getSsq("city");
      });
    },
    handleSelectCity(item) {
      this.selectionOptions.city = item;
      this.$emit("input", [...this.value, item]);
      this.address = `${this.selectionOptions.prov.name}/${this.selectionOptions.city.name}`;
      this.current = "area";
      this.searchKey = "";
      this.$nextTick(() => {
        this.getSsq("area");
      });
    },
    handleSelectArea(item) {
      this.selectionOptions.area = item;
      this.$emit("input", [...this.value, item]);
      this.address = `${this.selectionOptions.prov.name}/${this.selectionOptions.city.name}/${this.selectionOptions.area.name}`;
      this.handleCancelPopover();
      this.searchKey = "";
    },
    handleCancelPopover() {
      this.visible = false;
    },
    handleSearch() {
      const key = this.searchKey;
      const type = this.current;
      this.querySearch(key, res => {
        this.list[type] = res;
      });
    },
    querySearch(key = "", cb) {
      const original = this.original[this.current];
      const results = key ? original.filter(this.createFilter(key)) : original;
      cb && cb(results);
    },
    createFilter(queryString) {
      return ({ name }) => {
        return name.toLowerCase().indexOf(queryString.toLowerCase()) === 0;
      };
    },
    handleAddInputObserver() {
      const that = this;
      const $element = document.querySelectorAll(".el-dialog");
      const $popper = document.querySelectorAll(".address-select-popover");
      const $trigger = document.querySelectorAll(".trigger-area");
      if (!$trigger || !$element) return;
      for (let i = 0; i < $trigger.length; i++) {
        sessionStorage.setItem(`lock${i}`, "false");
      }
      const MutationObserver =
        window.MutationObserver ||
        window.WebKitMutationObserver ||
        window.MozMutationObserver;
      const observer = new MutationObserver(function(mutations) {
        const fixPosition = function() {
          for (let i = 0; i < $popper.length; i++) {
            if (
              !$popper[i].style.display &&
              sessionStorage.getItem(`lock${i}`) === "false"
            ) {
              $trigger[i].click();
              sessionStorage.setItem(`lock${i}`, "true");
            }
          }
        };
        fixPosition();
      });
      const parentObserver = new MutationObserver(function(mutations) {
        for (let i = 0; i < $element.length; i++) {
          if (
            $element[i] &&
            $element[i].parentElement.style.display === "none"
          ) {
            // 存在多个dialog的时候 出现自动关闭的bug
            // that.handleCancelPopover()
          }
        }
      });
      for (let i = 0; i < $element.length; i++) {
        if ($element[i].parentElement.style.display !== "none") {
          $element && observer.observe($element[i], { attributes: true });
          $element &&
            parentObserver.observe($element[i].parentElement, {
              attributes: true
            });
        }
      }
    },
    getSsq(queryType) {
      let _this=this;
      const obj = {};
      if (queryType === "city") {
        obj.prov = this.selectionOptions.prov.name;
        obj.queryType = "city";
      } else if (queryType === "area") {
        obj.prov = this.selectionOptions.prov.name;
        obj.city = this.selectionOptions.city.name;
      }
      if (this.url === "") {
        this.$Api.order
          .getSsq({
            country: this.country,
            queryType,
            ...obj
          })
          .then(res => {
            this.list[this.current] = res.data || [];
            this.original[this.current] = res.data || [];
          });
      } else {
        const hasToken = getToken();
        let param = {
          parameter: { country: this.country, queryType, ...obj },
          token: hasToken
        };
        Axios.post(this.url, param).then(res => {
          _this.list[_this.current] = res.data.data || [];
          _this.original[_this.current] = res.data.data || [];
        });
      }
    }
  }
};
</script>

<style lang="scss">
@import "../styles/mixin.scss";
@import "../styles/variables.scss";
.trigger-area {
  position: relative;
  .el-input__inner {
    cursor: pointer;
  }
  .flag-icon {
    color: #c0c4cc;
    position: absolute;
    right: 12px;
    top: 10px;
    transition: 0.3s ease all;
  }
  .rotate-arrow {
    transform: rotate(-180deg);
  }
}
.address-select-popover {
  border-radius: 2px;
  margin-top: 2px !important;
  padding: 0;
  border: 0;
  overflow: hidden;
  .address-tab {
    box-shadow: none;
    .search-area {
      padding: 0 15px;
    }
    .el-tabs__content {
      position: relative;
      font-size: 12px;
      padding: 15px 0;
      .list-area {
        height: 200px;
        margin-top: 10px;
        .el-scrollbar__wrap {
          overflow-x: hidden;
          .el-scrollbar__view {
            padding: 0 15px;
          }
        }
        .address-item {
          line-height: 24px;
          @include hover-color($info, $skyBlue);
          padding: 0 10px;
          &.current {
            background-color: $skyBlue;
            color: white;
          }
          &.selectColor {
            background-color: $light-blue;
            color: #fff;
          }
          &.noselectColor {
            background-color: #fff;
            color: #909399;
          }
        }
      }
      .search-ipt {
      }
    }
    .el-tabs__item {
      height: 32px;
      line-height: 32px;
      font-size: 12px;
    }
  }
}
</style>
