<template>
  <div id="tower">
    <div class="side-area">
      <Title text="设备总览"></Title>
      <ShadowContainer>
        <div class="chart-container">
          <img class="custom-chart" src="@/assets/chart.png" />
          <div ref="deviceChart" id="device-chart"></div>
        </div>
      </ShadowContainer>
      <Title text="各塔吊24h力矩百分比统计"></Title>
      <ShadowContainer>
        <div id="force-chart" ref="forceChart"></div>
      </ShadowContainer>
      <Title text="各塔吊24h倾角统计"></Title>
      <ShadowContainer>
        <div id="dip-chart" ref="dipChart"></div>
      </ShadowContainer>
    </div>
    <div id="mid-area">
      <div class="towerwindow" v-if="towerWindowVisible">
        <div class="tower-description">
          <img
            :src="
              windowData.is_online == 1
                ? require('@/assets/zhongji_online.png')
                : require('@/assets/zhongji.png')
            "
            alt=""
          />
          {{ windowData.device_no }} /
          <span
            :class="[
              'online-status',
              windowData.is_online == 1 ? 'online' : 'offline',
            ]"
            >{{ windowData.is_online_text }}</span
          >
          <span @click="openDetailDialog" class="name" style="cursor: pointer"
            >详情
            <img
              style="width: 20px; vertical-align: top; margin-top: 4px"
              src="@/assets/tower/arrow.png"
              alt=""
            />
          </span>
        </div>
        <div class="recent-open">最近使用:{{ windowData.log_time }}</div>
      </div>
      <div class="swagger-container" id="container">
        <img class="lt" src="@/assets/lt.png" alt="" />
        <img class="rt" src="@/assets/rt.png" alt="" />
        <img class="rb" src="@/assets/rb.png" alt="" />
        <img class="lb" src="@/assets/lb.png" alt="" />
        <div id="amap-container"></div>
      </div>
    </div>
    <div class="side-area">
      <Title text="报警信息"></Title>
      <ShadowContainer>
        <div class="warn-message">
          <div class="warn-icon" v-if="warnings.length == 0">
            <img src="@/assets/no-message.png" alt="" />
            <div>暂无信息~</div>
          </div>
          <div class="warp" v-else>
            <div
              class="warn-title"
              v-for="(warn, index) in warnings"
              :key="index"
            >
              <div class="warn-text">
                <el-tooltip
                  class="item"
                  effect="dark"
                  :content="`${warn.alarm_content}(${warn.device_no})`"
                >
                  <div class="overflowed">
                    {{ warn.alarm_content }}({{ warn.device_no }})
                  </div>
                </el-tooltip>
              </div>
              <div class="warn-time">{{ warn.log_time }}</div>
            </div>
          </div>
        </div>
      </ShadowContainer>
      <Title text="设备列表"></Title>
      <ShadowContainer>
        <div class="monitor-list">
          <div
            class="noise-monitor"
            v-for="(monitor, index) in monitors"
            :key="index"
            @click="moveToMonitor(monitor)"
          >
            <img
              :src="
                monitor.is_online == 1
                  ? require('@/assets/zhongji_online.png')
                  : require('@/assets/zhongji.png')
              "
              alt=""
            />
            {{ monitor.device_no }}
            <span
              :style="{
                color: monitor.is_online_text == '在线' ? '#3eec6f' : '',
              }"
              >{{ monitor.is_online_text }}</span
            >
          </div>
        </div>
      </ShadowContainer>
    </div>

    <device-dialog
      :deviceId="windowData.id"
      :deviceData="deviceData"
      :visible="deviceDialogVisible"
      @changeVisible="(val) => (deviceDialogVisible = val)"
    ></device-dialog>
  </div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import onlineIcon from "@/assets/tower/online_tower.png";
import offlineIcon from "@/assets/tower/offline_tower.png";
import deviceDialog from "./deviceDialog.vue";
import hooks from "@/assets/tower/hooks.png";
import {
  getBaseInfo,
  getTowerDevice,
  get24hTowerStatis,
  getTowerWarnings,
  getTowerDeviceList,
  getCurrentTowerStatis,
  getDeviceDetail,
} from "@/api/index";
export default {
  name: "Tower",
  components: { deviceDialog },
  data() {
    return {
      pieChartData: [],
      warnings: [],
      monitors: [],
      mapCenter: [],
      AMap: null,
      map: null,
      towerWindowVisible: false,
      windowData: {},
      polyLineArray: [],
      timer: null,
      deviceDialogVisible: false,
      deviceData: {},
      markerArray: [],
    };
  },
  methods: {
    renderDeviceChart() {
      const pieData = [...this.pieChartData];
      const chart = this.$echarts.init(this.$refs.deviceChart);
      let total = 0;
      pieData.map((item) => {
        total += item.value;
      });
      const option = {
        title: {
          x: "27%", //X坐标
          y: "35%",
          text: total,
          subtext: "总数",
          textAlign: "center",
          textStyle: {
            //标题样式
            fontSize: 30,
            fontWeight: "bolder",
            color: "#00fcff",
          },
          subtextStyle: {
            //副标题样式
            fontSize: 16,
            fontWeight: "bolder",
            color: "rgba(255,255,255,0.7)",
          },
        },
        tooltip: {
          trigger: "item",
        },
        legend: {
          itemHeight: 12,
          itemWidth: 12,
          icon: "rect",
          right: "10%",
          top: "15%",
          orient: "vertical",
          itemGap: 40,
          textStyle: {
            color: "inherit",
            rich: {
              a: {
                fontSize: 14,
                align: "left",
              },
              b: {
                fontSize: 20,
                align: "left",
                lineHeight: 25,
              },
            },
          },
          formatter: (name) => {
            let data = pieData;
            let target;
            for (let i = 0, l = data.length; i < l; i++) {
              if (data[i].name == name) {
                target = data[i].value;
              }
            }
            let arr = [`{a|${name}}`, `{b|${target}} 台`];
            return arr.join("   ");
          },
        },
        series: [
          {
            type: "pie",
            radius: ["80%", "90%"],
            center: ["28%", "50%"],
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 20,
              borderWidth: 4,
            },
            label: {
              show: false,
              position: "center",
            },
            data: pieData,
          },
        ],
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("device-chart"));
      });
    },
    renderForceChart() {
      const xAxisData = this.towerData[0].data.map((item) => {
        return item.time;
      });
      const seriesData = this.towerData.map((series) => {
        return {
          name: series.name,
          type: "line",
          smooth: true,
          data: series.data.map((item) => {
            return item.moment_rate;
          }),
        };
      });
      const chart = this.$echarts.init(this.$refs.forceChart);
      const option = {
        grid: {
          top: 30,
          bottom: 30,
          left: 30,
          right: 30,
        },
        legend: {
          orient: "horizontal",
          x: "center",
          y: "top",
          textStyle: {
            fontSize: 12,
            color: "rgba(225, 239, 255, 0.7)",
          },
        },
        tooltip: {
          trigger: "item",
        },
        xAxis: {
          type: "category",
          data: xAxisData,
          axisTick: { show: false },
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
        },
        yAxis: {
          type: "value",
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
          splitNumber: 4,
          splitLine: {
            lineStyle: {
              color: "rgba(95, 120, 144, 0.4)",
            },
          },
        },
        series: seriesData,
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("force-chart"));
      });
    },
    renderDipChart() {
      const xAxisData = this.towerData[0].data.map((item) => {
        return item.time;
      });
      const seriesData = this.towerData.map((series) => {
        return {
          name: series.name,
          type: "line",
          smooth: true,
          data: series.data.map((item) => {
            return item.dip_angle;
          }),
        };
      });
      const chart = this.$echarts.init(this.$refs.dipChart);
      const option = {
        grid: {
          top: 30,
          bottom: 30,
          left: 30,
          right: 30,
        },
        legend: {
          orient: "horizontal",
          x: "center",
          y: "top",
          textStyle: {
            fontSize: 12,
            color: "rgba(225, 239, 255, 0.7)",
          },
        },
        xAxis: {
          type: "category",
          data: xAxisData,
          axisTick: { show: false },
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
        },
        yAxis: {
          type: "value",
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
          splitNumber: 4,
          splitLine: {
            lineStyle: {
              color: "rgba(95, 120, 144, 0.4)",
            },
          },
        },
        series: seriesData,
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("dip-chart"));
      });
    },
    getTowerData() {
      getTowerDevice({ top_cat: 1, child_cat: 1 }).then((res) => {
        this.pieChartData = res.data;
        this.renderDeviceChart();
      });
      get24hTowerStatis().then((res) => {
        this.towerData = res.data;
        this.renderForceChart();
        this.renderDipChart();
      });
      getTowerWarnings().then((res) => {
        this.warnings = res.data;
      });

      getBaseInfo().then((res) => {
        this.mapCenter = [res.data.longitude, res.data.latitude];
        this.$nextTick(() => {
          this.initMap();
        });
      });
    },
    initMap() {
      AMapLoader.load({
        key: "fc00c5b70f67a8414344682f217d4b6e",
        version: "1.4.15",
        plugins: ["AMap.MarkerClusterer", "AMap.DistrictSearch"],
      })
        .then((AMap) => {
          // 初始化地图
          this.AMap = AMap;
          this.map = new AMap.Map("amap-container", {
            viewMode: "2D",
            zoom: 19,
            center: this.mapCenter,
            resizeEnable: true,
            mapStyle: "amap://styles/darkblue",
          });
          this.map.on("click", (e) => {
            console.log(e);
            this.towerWindowVisible = false;
          });
          getTowerDeviceList().then((res) => {
            this.monitors = res.data;
            this.setMarker();
          });
        })
        .catch((e) => {
          console.log(e);
        });
    },
    setMarker() {
      this.monitors.map((marker) => {
        const mapMarkers = new this.AMap.Marker({
          icon: marker.is_online == 1 ? onlineIcon : offlineIcon,
          position: [marker.longitude, marker.latitude],
          offset: new this.AMap.Pixel(-25, -25),
          extData: {
            markerData: marker,
          },
        });
        mapMarkers.setMap(this.map);
        mapMarkers.on("click", (e) => {
          const markData = e.target.getExtData().markerData;
          this.map.setCenter([markData.longitude, markData.latitude]);
          this.windowData = markData;
          this.$nextTick(() => {
            this.towerWindowVisible = true;
          });
        });
        const circles = new this.AMap.Circle({
          center: [marker.longitude, marker.latitude], // 圆心位置
          radius: marker.arm_length, //半径
          strokeColor: "#FF33FF", //线颜色
          strokeOpacity: 0.5, //线透明度
          strokeWeight: 3, //线宽
          strokeStyle: "dashed",
          fillColor: "#1791fc", //填充色
          fillOpacity: 0.2, //填充透明度
        });
        circles.setMap(this.map);
      });
      this.getCurrentTowerStatis();
      this.timer = setInterval(() => {
        this.getCurrentTowerStatis();
      }, 60000);
    },
    moveToMonitor(monitor) {
      this.map.setCenter([monitor.longitude, monitor.latitude]);
      this.windowData = monitor;
      this.towerWindowVisible = true;
    },
    openDetailDialog() {
      getDeviceDetail(this.windowData.id).then((res) => {
        this.deviceData = res.data;
        this.$nextTick(() => {
          this.deviceDialogVisible = true;
        });
      });
    },
    getLngAndLat(lng, lat, brng, dist) {
      var a = 6378137;
      var b = 6356752.3142;
      var f = 1 / 298.257223563;
      var lon1 = lng * 1;
      var lat1 = lat * 1;
      var s = dist;
      var alpha1 = this.rad(brng - 90);
      var sinAlpha1 = Math.sin(alpha1);
      var cosAlpha1 = Math.cos(alpha1);

      var tanU1 = (1 - f) * Math.tan(this.rad(lat1));
      var cosU1 = 1 / Math.sqrt(1 + tanU1 * tanU1),
        sinU1 = tanU1 * cosU1;
      var sigma1 = Math.atan2(tanU1, cosAlpha1);
      var sinAlpha = cosU1 * sinAlpha1;
      var cosSqAlpha = 1 - sinAlpha * sinAlpha;
      var uSq = (cosSqAlpha * (a * a - b * b)) / (b * b);
      var A =
        1 + (uSq / 16384) * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
      var B = (uSq / 1024) * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));

      var sigma = s / (b * A),
        sigmaP = 2 * Math.PI;
      while (Math.abs(sigma - sigmaP) > 1e-12) {
        var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
        var sinSigma = Math.sin(sigma);
        var cosSigma = Math.cos(sigma);
        var deltaSigma =
          B *
          sinSigma *
          (cos2SigmaM +
            (B / 4) *
              (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
                (B / 6) *
                  cos2SigmaM *
                  (-3 + 4 * sinSigma * sinSigma) *
                  (-3 + 4 * cos2SigmaM * cos2SigmaM)));
        sigmaP = sigma;
        sigma = s / (b * A) + deltaSigma;
      }

      var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
      var lat2 = Math.atan2(
        sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
        (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp)
      );
      var lambda = Math.atan2(
        sinSigma * sinAlpha1,
        cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1
      );
      var C = (f / 16) * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
      var L =
        lambda -
        (1 - C) *
          f *
          sinAlpha *
          (sigma +
            C *
              sinSigma *
              (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

      // var revAz = Math.atan2(sinAlpha, -tmp); // final bearing

      var lngLatObj = {
        lng: lon1 + this.deg(L),
        lat: this.deg(lat2),
      };
      return lngLatObj;
    },
    rad(d) {
      return (d * Math.PI) / 180.0;
    },
    deg(d) {
      return (d * 180) / Math.PI;
    },
    getCurrentTowerStatis() {
      this.polyLineArray.map((item) => {
        this.map.remove(item);
      });
      this.markerArray.map((item) => {
        this.map.remove(item);
      });
      const monitorIds = this.monitors
        .map((item) => {
          return item.id;
        })
        .join(",");
      getCurrentTowerStatis({ device_ids: monitorIds }).then((res) => {
        res.data.map((monitor) => {
          const filterItem = this.monitors.filter((item) => {
            return monitor.device_id == item.id;
          })[0];
          const startPosition = [filterItem.longitude, filterItem.latitude];
          const endPosition = [
            this.getLngAndLat(
              filterItem.longitude,
              filterItem.latitude,
              monitor.rotation,
              filterItem.arm_length
            ).lng,
            this.getLngAndLat(
              filterItem.longitude,
              filterItem.latitude,
              monitor.rotation, //0度是正东
              filterItem.arm_length
            ).lat,
          ];
          this.polyLineArray.push(
            new this.AMap.Polyline({
              map: this.map,
              path: [startPosition, endPosition],
            })
          );
          const markersPosition = [
            this.getLngAndLat(
              filterItem.longitude,
              filterItem.latitude,
              monitor.rotation,
              monitor.amplitude
            ).lng,
            this.getLngAndLat(
              filterItem.longitude,
              filterItem.latitude,
              monitor.rotation, //0度是正东
              monitor.amplitude
            ).lat,
          ];
          const markers = new this.AMap.Marker({
            icon: hooks,
            position: markersPosition,
            offset: new this.AMap.Pixel(-25, -25),
          });
          this.markerArray.push(markers);
          markers.setMap(this.map);
        });
      });
    },

    resetMapSize() {
      let screenWidth =
        document.body.clientWidth || document.documentElement.clientWidth;
      let defWidth = 1920;
      let xScale = screenWidth / defWidth;
      let mapContent = document.getElementById("container");
      mapContent.style.zoom = 1 / xScale;
      mapContent.style.height = xScale * 960 + "px";
    },
  },
  mounted() {
    this.getTowerData();
    this.resetMapSize();
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
};
</script>
<style lang="less" scoped>
@import "@/assets/common/element.less";
#tower {
  padding: 12px 20px;
  display: flex;
  justify-content: space-between;
  .side-area {
    width: 25%;
  }
  #mid-area {
    width: calc(50% - 40px);
    margin: 0 20px;
    position: relative;
  }
}
.swagger-container {
  position: relative;
  .container-img {
    width: 100%;
    height: 960px;
    vertical-align: top;
  }
  .lt,
  .lb,
  .rb,
  .rt {
    position: absolute;
    width: 20px;
    height: 20px;
  }
  .lt {
    top: -2px;
    left: -2px;
  }
  .lb {
    left: -2px;
    bottom: -2px;
  }
  .rb {
    right: -2px;
    bottom: -2px;
  }
  .rt {
    right: -2px;
    top: -2px;
  }
}
#force-chart,
#dip-chart {
  width: 100%;
  height: 210px;
}
.chart-container {
  position: relative;
  .custom-chart {
    position: absolute;
    width: 30%;
    top: 50%;
    transform: translateY(-50%);
    left: 13%;
  }
}
#device-chart {
  width: 100%;
  height: 210px;
}
.tower-name {
  background: rgba(255, 175, 81, 0.1);
  border: 1px solid #ffaf51;
  font-size: 16px;
  font-family: Microsoft YaHei;
  font-weight: bold;
  color: #ffaf51;
  display: inline-block;
  padding: 6px 12px;
  letter-spacing: 1px;
}
.steps {
  padding-top: 20px;
}
.step-title {
  position: relative;

  color: #fff;
  font-size: 12px;

  .step-status {
    position: absolute;
    top: -170%;
    color: #18d7b9;
    font-size: 12px;
  }
}
.step-description {
  font-size: 14px;
  color: #22c3ed;
}

.warn-message {
  position: relative;
  height: 420px;
  overflow-y: auto;
  .warn-icon {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(-50%);
    color: #063e6c;
    font-size: 16px;
    text-align: center;
    img {
      width: 100px;
    }
  }
}

.warn-title {
  border-left: 2px solid;
  padding-left: 12px;
  font-size: 14px;
  color: #c6def9;
  display: flex;
  justify-content: space-between;
  margin-bottom: 18px;
  &:nth-child(3n-2) {
    border-color: #fd175d;
  }
  &:nth-child(3n-1) {
    border-color: #ab75ff;
  }
  &:nth-child(3n) {
    border-color: #ffbb37;
  }
  .warn-text {
    width: 60%;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  .warn-time {
    width: 40%;
    text-align: right;
  }
}
.monitor-list {
  height: 320px;
  overflow-y: auto;
}
.noise-monitor {
  font-size: 14px;
  color: #c6def9;
  line-height: 72px;
  background: rgba(44, 96, 162, 0.05);
  padding: 0 12px;
  margin-bottom: 12px;
  cursor: pointer;
  &:last-child {
    margin-bottom: 0;
  }
  &:hover {
    color: #27acfb;
    background: rgba(44, 96, 162, 0.2);
  }
  img {
    width: 30px;
    height: 30px;
    margin-top: 20px;
    margin-right: 12px;
    vertical-align: top;
  }
  .device-description {
    line-height: 36px;
    width: 70%;
  }
  .online {
    color: #3eec6f;
  }
  span {
    float: right;
  }
}
#amap-container {
  width: 100%;
  height: 100%;
}
.swagger-container {
  width: 100%;
  height: 100%;
}
::v-deep .amap-icon {
  img {
    width: 50px;
    height: 50px;
  }
}

.towerwindow {
  width: 460px;
  height: 90px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-120%);
  background: url("@/assets/safecap/cap-window-bg.png") no-repeat;
  background-size: 100% 100%;
  padding: 20px;
  z-index: 1000;
}
.recent-open {
  font-size: 16px;
  color: #c6def9;
  line-height: 60px;
}
.tower-description {
  line-height: 32px;
  font-size: 18px;
  color: #c6def9;
  padding-bottom: 16px;
  border-bottom: 1px solid #7a8fad;
  img {
    width: 32px;
    vertical-align: top;
  }
  .name {
    float: right;
  }
  .online-status.online {
    color: rgba(62, 236, 111, 1);
  }
}
</style>