<template>
  <div ref="root" class="el-affix" :style="rootStyle">
    <div :class="{ 'el-affix--fixed': fixed }" :style="affixStyle">
      <slot></slot>
    </div>
  </div>
</template>

<script>
import throttle from "throttle-debounce/throttle";
import { isUndefined, isWindow } from "modesign-ui/src/utils/types";
import {
  addResizeListener,
  removeResizeListener,
} from "modesign-ui/src/utils/resize-event";
const COMPONENT_NAME = "ElAffix";
export default {
  name: "ElAffix",

  props: {
    offset: {
      type: Number,
      default: 0,
    },
    position: {
      type: String,
      values: ["top", "bottom"],
      default: "top",
    },
    target: {
      type: String,
      default: "",
    },
    targetContainer: {},
    // affix是相对target滚动容器还是window进行定位的
    relative: {
      type: String,
      values: ["self", "window"],
      default: "window",
    },
    zIndex: {
      type: Number,
      default: 100,
    },
  },
  data() {
    return {
      fixed: false,
      rootHeight: null,
      rootWidth: null,
      transform: 0,
      scrollTop: 0,
      scrollContainer: "",
      el: "",
      affixStyle: null,
      container: null
    };
  },

  computed: {
    rootStyle() {
      return {
        height: this.fixed ? `${this.rootHeight}px` : "",
        width: this.fixed ? `${this.rootWidth}px` : "",
      };
    },
  },

  watch: {
    fixed(val) {
      this.$emit("change", val);
    },
  },

  mounted() {
    this.scrollContainer = window;
    this.el = document.documentElement;
    // this.throttledScrollHandler = throttle(300, this.onScroll);
    if (this.target) {
      this.el = document.querySelector(this.target);
      if (!this.el)
        throw new Error(
          COMPONENT_NAME,
          `Target is not existed: ${this.target}`
        );
      this.scrollContainer = this.el;
    }

    this.scrollContainer.addEventListener("scroll", this.handleScroll);
    this.scrollContainer.addEventListener("resize", this.handleScroll);
    this.updateState();
    

    this.container =
      (this.targetContainer &&
        this.targetContainer !== window &&
        document.querySelector(this.targetContainer)) ||
      window;
    if (this.container) {
      this.container.addEventListener("scroll", this.handleScroll);
      this.container.addEventListener("resize", this.handleScroll);
    }
  },

  methods: {
    handleScroll() {
      // 更新固钉状态
      this.updateState();
      this.$emit("scroll", {
        scrollTop: this.scrollTop,
        fixed: this.fixed,
      });
    },

    // 更新固钉状态函数
    updateState() {
      const root = this.$refs.root;
      const rootRect = root.getBoundingClientRect();
      let targetRect;
      if (isWindow(this.scrollContainer)) {
        targetRect = document.documentElement.getBoundingClientRect();
      } else {
        targetRect = this.scrollContainer.getBoundingClientRect();
      }
      this.rootHeight = rootRect.height;
      this.rootWidth = rootRect.width;
      this.scrollTop = isWindow(this.scrollContainer)
        ? document.documentElement.scrollTop
        : this.scrollContainer.scrollTop;
      this.clientHeight = document.documentElement.clientHeight;
      // 如果固定在顶部
      if (this.position === "top") {
        if (this.target) {
          // 如果是相对于window进行定位的，即不是单独在某个指定的容器内
          if (this.relative == "window") {
            // 如果target不是window，即滚动条的顶部不能滚动到可视区域的最顶端
            // if (this.scrollContainer === window) {
            //   this.fixed = rootRect.top - targetRect.top < (this.offset || 0);
            // } else {
            //   this.fixed = rootRect.top < (this.offset || 0);
            // }
            this.fixed = rootRect.top < (this.offset || 0);
          } else if (this.relative == "self") {
            this.fixed = rootRect.top - targetRect.top < (this.offset || 0);
          }
        } else {
          this.fixed = this.offset > rootRect.top;
        }
        this.getAffixStyle(targetRect);
      } else {
        if (this.target) {
          if (this.relative == "window") {
            this.fixed =
              this.clientHeight - this.offset < rootRect.bottom &&
              this.clientHeight > targetRect.top;
          } else if (this.relative == "self") {
            this.fixed =
              targetRect.bottom - rootRect.bottom > (this.offset || 0);
          }
        } else {
          this.fixed = this.clientHeight - this.offset < rootRect.bottom;
        }
        this.getAffixStyle(targetRect, this.clientHeight);
      }
    },

    // 获取affixStyle
    getAffixStyle(targetRect, clientHeight) {
      if (this.fixed) {
        let offset = 0;
        if (this.offset) {
          if (this.position == "top") {
            if (this.relative == "window") {
              offset = `${this.offset}px`;
            } else {
              offset = `${targetRect.top + this.offset}px`;
            }
          } else {
            if (this.relative == "window") {
              offset = `${this.offset}px`;
            } else {
              offset = `${clientHeight - targetRect.bottom + this.offset}px`;
            }
          }
        }

        this.affixStyle = {
          height: `${this.rootHeight}px`,
          width: `${this.rootWidth}px`,
          top: this.position == "top" ? offset : "",
          bottom: this.position == "bottom" ? offset : "",
          zIndex: this.zIndex,
        };
      } else {
        this.affixStyle = {};
      }
    },
  },

  beforeDestroy() {
    this.scrollContainer.removeEventListener("scroll", this.handleScroll);
    this.scrollContainer.removeEventListener("resize", this.handleScroll);

    if (this.container) {
      this.container.removeEventListener("scroll", this.handleScroll);
      this.container.removeEventListener("resize", this.handleScroll);
    }
  },
};
</script>

<style lang="scss" scoped>
</style>
