import React from "react";

import { AmsChart } from "react-meteo-chart";
import { Query, ApolloProvider } from "react-apollo";

import moment from "moment";
import ApolloClient from "apollo-boost";
import ReactLoading from "react-loading";
import Select from "react-select";
import gql from "graphql-tag";
import "./style.css";
const day = 86400000;

const windDirectionHandler = (msgs, minmax, height) => {
  let arr = [];
  let dy = minmax[1] - minmax[0];
  let y_dir = minmax[0] - dy / 5;

  arr = msgs
    .filter((e, i) => e[1] !== null)
    .map((point) => {
      switch (point[1]) {
        case 0:
          return {
            x: point[0] * 1000,
            y: y_dir,
            customComponent: "circle",
            size: 10,
            style: { stroke: "black", fill: "white" },
            z: 0,
          };
        case 99:
          return {
            x: point[0],
            y: y_dir,
            customComponent: "circle",
            size: 20,
            style: { stroke: "black", fill: "white" },
            z: 0,
          };
        default:
          const val = point[1];
          let velocity = point[2];

          let triNum = Math.floor(velocity / 25);
          let longfeathNum = Math.floor((velocity % 25) / 5);
          let leftVelocity =
            velocity > 1 ? velocity - triNum * 25 - longfeathNum * 5 : 0;

          let translate = 0;
          let things = [];
          if (velocity <= 1)
            if (val <= 180)
              things.push(
                <path
                  d="M489.33 178.76C489.33 191.29 479.56 201.46 467.52 201.46C455.48 201.46 445.7 191.29 445.7 178.76C445.7 166.24 455.48 156.07 467.52 156.07C479.56 156.07 489.33 166.24 489.33 178.76Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
            else
              things.push(
                <path
                  d="M443.63 344C443.63 356.53 433.86 366.7 421.82 366.7C409.78 366.7 400 356.53 400 344C400 331.47 409.78 321.3 421.82 321.3C433.86 321.3 443.63 331.47 443.63 344Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
          for (let i = 0; i < triNum; i++) {
            if (val <= 180)
              things.push(
                <path
                  transform={`translate(${-translate})`}
                  d="M389.38 126.04L257.46 257.96L389.38 257.96L389.38 126.04Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
            else
              things.push(
                <path
                  transform={`translate(${-translate})`}
                  d="M389.59 409.96L257.68 278.04L389.59 278.04L389.59 409.96Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
            translate += 120;
          }
          for (let i = 0; i < longfeathNum; i++) {
            if (val <= 180)
              things.push(
                <path
                  transform={`translate(${-translate})`}
                  d="M514.03 149.92L387.53 281.28L373.08 267.36L499.58 136L514.03 149.92Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
            else
              things.push(
                <path
                  transform={`translate(${-translate})`}
                  d="M520 391.41L389.6 256L375.15 269.92L505.55 405.33L520 391.41Z"
                  key={`${val}${point[0]}${translate}`}
                />
              );
            translate += 60;
          }
          if (leftVelocity) {
            if (leftVelocity < 4) {
              if (val <= 180)
                things.push(
                  <path
                    transform={`translate(${-translate})`}
                    d="M460.19 207.58L390.45 280L376 266.08L445.74 193.66L460.19 207.58Z"
                    key={`${val}${point[0]}${translate}`}
                  />
                );
              else
                things.push(
                  <path
                    transform={`translate(${-translate})`}
                    d="M460.19 328.42L390.45 256L376 269.92L445.74 342.34L460.19 328.42Z"
                    key={`${val}${point[0]}${translate}`}
                  />
                );
            } else if (leftVelocity < 5) {
              if (val <= 180)
                things.push(
                  <path
                    transform={`translate(${-translate})`}
                    d="M514.03 149.92L387.53 281.28L373.08 267.36L499.58 136L514.03 149.92Z"
                    key={`${val}${point[0]}${translate}`}
                  />
                );
              else
                things.push(
                  <path
                    transform={`translate(${-translate})`}
                    d="M520 391.41L389.6 256L375.15 269.92L505.55 405.33L520 391.41Z"
                    key={`${val}${point[0]}${translate}`}
                  />
                );
            }
          }

          return {
            x: point[0] * 1000,
            y: y_dir,
            customComponent: (row, positionInPixels) => {
              return (
                <g
                  // transform={` scale(0.10) `}
                  transform={` scale(0.080) rotate(${val - 90} 270 270)`}
                  // transformOrigin={"2000% 50%"}
                  version="1.1"
                  id="Layer_1"
                  xmlns="http://www.w3.org/2000/svg"
                  x="0"
                  y="0"
                  viewBox="0 0 512 512"
                  style={{ fill: "#50C8EF" }}
                  // style="enable-background:new 0 0 512 512;"
                >
                  <path
                    d="M24 255.18L389.57 255.18L389.57 280L24 280L24 255.18Z"
                    key={`${point[0]}-1`}
                  />

                  <path
                    d="M50.34 267.54L114.23 306.46L89.08 321.79L46.62 295.92L46.58 295.94L0 267.56L0.03 267.54L0 267.53L46.58 239.15L46.61 239.17L89.08 213.3L114.22 228.62L50.34 267.54Z"
                    key={`${point[0]}-2`}
                  />
                  {things.map((d) => d)}

                  {/* <rect
                    y="227.558"
                    style={{ fill: "#50C8EF" }}
                    width="455.117"
                    height="56.883"
                  />
                  <polygon
                    style={{ fill: "#50C8EF" }}
                    points="278.566,390.774 250.117,341.507 398.226,256 250.117,170.491 278.566,121.226 512,256 	"
                  /> */}
                </g>
              );
            },
            z: val,
          };
      }
    });
  arr.push({
    x: arr[0] ? arr[0].x : null,
    y: minmax[0] - dy / 1.5,
    customComponent: "circle",
    size: 0,
    style: { stroke: "black", fill: "white" },
    z: 0,
  });
  return arr;
};

const currentStation = gql`
  query amsPlotData(
    $token: String!
    $stationId: String!
    $since: DateTime
    $to: DateTime
    $typeName: String!
    $maxPoints: Int
  ) {
    amsPlotData(
      token: $token
      stationId: $stationId
      typeName: $typeName
      since: $since
      to: $to
      maxPoints: $maxPoints
    )
  }
`;
const ME = gql`
  query($token: String!) {
    me(token: $token) {
      lastLogin
    }
  }
`;

const selecterStyle = {
  control: (base, state) => ({
    ...base,

    backgroundColor: "ccccff",
    opacity: 1,
    height: "12px",
    width: "100px",
    border: state.isFocused ? 0 : 0,
    boxShadow: state.isFocused ? 0 : 0,
    "&:hover": {
      border: state.isFocused ? 0 : 0,
    },
  }),

  dropdownIndicator: (e) => ({
    ...e,
    color: "#646464",
    transform: "rotate(180deg)",
  }),
  menu: (e) => ({
    ...e,
    color: "#00000",
    width: "100px",
    backgroundColor: "#ffFffF",
  }),
};
const zooms = [
  [1, "d", "День"],
  [3, "d", "3 Дня"],
  [7, "d", "Неделя"],
  [14, "d", "2 Недели"],
];
const selectValues = [
  { label: "День", value: 0 },
  { label: "3 Дня", value: 1 },
  { label: "Неделя", value: 2 },
  { label: "2 Недели", value: 3 },
];
const zoomsvar = [3, 6, 12, 24];

// const selectedId = "22829";
// let dateFrom = "2019-03-23T06:30:00";
// let dateTo = "2019-03-25T06:30:00";
const types = ["ff", "TTT1", "tend", "RRR6", "dd_ff", "P0P0P0P03", "PPPP4"];
let minmax = [0, 0];

class AmsChartGen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      chunks: [],
      isLoadingChunks: [],
      chunksLength: [],
      zoom: 0,
      since: this.props.dateFrom
        ? moment(this.props.dateFrom).format("YYYY-MM-DDTHH:mm:ss")
        : null,
      to: moment(this.props.dateTo).format("YYYY-MM-DDTHH:mm:ss"),
      deep: true,
      wind: [],
      dataGap: this.props.dateTo,

      stationId: this.props.stationId,
      loadMessage:
        this.props.loadMessage !== undefined ? this.props.loadMessage : true,
    };
    this.deep = true;
    this.deepDarkFantasy = true;
    this.apollo = new ApolloClient({
      uri: this.props.client,
    });
  }
  componentDidUpdate() {
    if (
      this.state.to !==
      moment(this.props.dateTo).utc().format("YYYY-MM-DDTHH:mm:ss")
    ) {
      this.setState({
        to: moment(this.props.dateTo).utc().format("YYYY-MM-DDTHH:mm:ss"),
      });
      if (!this.props.animated) this.deep = true;
    }

    if (this.props.stationId !== this.state.stationId) {
      this.setState({
        stationId: this.props.stationId,
      });
      this.deep = true;
    }
  }
  dataTransformer = (data, indx, minmax) => {
    let chunk = [];
    switch (indx) {
      case 0:
        chunk = data.data.amsPlotData.map((s) => ({
          x: s[0] * 1000,
          y: s[1] !== null ? s[1] : "",
        }));
        break;
      case 3:
        data.data.amsPlotData.forEach((d) => {
          chunk = data.data.amsPlotData.map((s) => ({
            x0: s[0] * 1000,
            x: s[1] * 1000,
            y: s[2] !== null ? s[2] : "",
          }));
        });
        break;
      case 4:
        chunk = windDirectionHandler(
          data.data.amsPlotData,
          minmax,
          this.props.height
        );
        break;
      case 2:
        data.data.amsPlotData.forEach((d) => {
          chunk = data.data.amsPlotData
            .filter((d) => d[2] !== null)
            .map((s) => ({
              x: (s[0] * 1000 + s[1] * 1000) / 2,
              y: (s[4] + s[5]) / 2,
              yLow: s[2],
              yHigh: s[3],
              yOpen: s[4] > s[5] ? s[4] : s[5],
              yClose: s[4] > s[5] ? s[5] : s[4],

              color: s[4] > s[5] ? "#dd0000dd" : "#00dd00dd",
            }));
        });
        break;

      default:
        chunk = data.data.amsPlotData.map((s) => ({
          x: s[0] * 1000,
          y: s[1] !== null ? s[1] : "",
        }));
    }
    return chunk;
  };

  getTend = (variables) => {
    if (!this.props.dateFrom) return `${zoomsvar[this.state.zoom]}tend`;
    else {
      let gap =
        +moment(this.state.to).format("X") -
        +moment(this.state.since).format("X");
      if (gap <= 86400) return "3tend";
      else if (gap <= 86400 * 3) return "6tend";
      else if (gap <= 86400 * 7) return "12tend";
      else if (gap <= 86400 * 14) return "24tend";
      return "48tend";
    }
  };

  render() {
    let variables = {
      token: this.props.token,
      stationId: this.state.stationId,
      since: this.state.since
        ? this.state.since
        : moment(this.props.dateTo)
            .add(-zooms[this.state.zoom][0], zooms[this.state.zoom][1])
            .format("YYYY-MM-DDTHH:mm:ss"),
      to: moment(this.props.dateTo).format("YYYY-MM-DDTHH:mm:ss"),
      dataSince: moment(this.state.dataGap).add(
        -zooms[this.state.zoom][0],
        zooms[this.state.zoom][1]
      ),
      dataTo: moment(this.state.dataGap),

      maxPoints: this.props.maxPoints,
    };
    // if (this.state.chunks[0] && this.state.chunks[4]) {
    //   this.windDirectionHandler()
    // }
    if (this.props.doneLoading) {
      this.props.doneLoading(
        this.state.isLoadingChunks.filter((d) => d == false).length == 0 &&
          this.state.isLoadingChunks.length > 0
      );
    }
    let superArr = this.state.chunks.map((d) =>
      d
        .sort((a, b) => a.x > b.x)
        .filter(
          (s) =>
            s.x >= +moment.utc(variables.since).format("X") * 1000 &&
            s.x <= +moment.utc(variables.to).format("X") * 1000
        )
    );
    // console.log("since  :", moment.utc(variables.since).format("X"));
    // console.log("to  :", moment.utc(variables.to).format("X"));
    // console.log("superArr :", superArr);

    // TODO: Сделать нормальную проверку границ
    if (
      +moment(variables.since).format("X") < +variables.dataSince.format("X") &&
      this.props.dir == -1
    ) {
      // this.deepDarkFantasy = false;
      this.preFetch(this.props.dir);
    }
    if (
      +moment(variables.to).format("X") > +variables.dataTo.format("X") &&
      this.props.dir == 1
    ) {
      // this.deepDarkFantasy = false;
      this.preFetch(this.props.dir);
    }

    return (
      <ApolloProvider client={this.apollo}>
        <div className="App">
          {this.state.isLoadingChunks.filter((d) => d == false).length > 0 &&
            this.state.loadMessage && (
              <div
                style={{
                  display: "flex",
                  justifyContent: "center",
                  alignContent: "center",
                  alignItems: "center",
                  flexDirection: "column",
                  fontSize: "17px",
                  height: "100%",
                }}
              >
                <ReactLoading
                  type="balls"
                  color="#333333"
                  height={25}
                  width={50}
                />{" "}
                <p> Загрузка графиков </p>
              </div>
            )}
          <Query query={ME} variables={{ token: variables.token }}>
            {({ loading, error, data, client }) => {
              if (loading) return <div />;
              if (error) return <p>Ошибка...</p>;

              if (!this.client) this.client = client;
              let req = [];
              {
                this.deep &&
                  types.forEach((t, indx) => {
                    req[indx] = client.query({
                      query: currentStation,
                      variables: {
                        token: variables.token,
                        stationId: variables.stationId,
                        typeName: indx == 2 ? this.getTend(variables) : t,
                        since: variables.since,
                        to: variables.to,
                        maxPoints:
                          indx == 4
                            ? this.props.maxPoints / 10
                            : this.props.maxPoints,
                      },
                    });
                    setTimeout(() =>
                      this.setState((state) => {
                        let chunk = false;

                        const isLoadingChunks = (state.isLoadingChunks[
                          indx
                        ] = chunk);

                        return isLoadingChunks;
                      })
                    );
                    if (indx == 4)
                      Promise.all([req[0], req[4]]).then((data) => {
                        let filtredData = data[0].data.amsPlotData.map(
                          (d) => d[1]
                        );
                        let minmax = [
                          Math.min(...filtredData),
                          Math.max(...filtredData),
                        ];

                        setTimeout(() =>
                          this.setState((state) => {
                            let chunk = this.dataTransformer(
                              data[1],
                              indx,
                              minmax
                            );
                            state.chunksLength[indx] = chunk.length;
                            state.chunks[indx] = chunk;
                          })
                        );
                        setTimeout(() =>
                          this.setState((state) => {
                            let chunk = true;
                            const isLoadingChunks = (state.isLoadingChunks[
                              indx
                            ] = chunk);
                            return isLoadingChunks;
                          })
                        );
                      });
                    else {
                      req[indx].then((data) => {
                        setTimeout(() =>
                          this.setState((state) => {
                            let chunk = this.dataTransformer(data, indx);
                            state.chunksLength[indx] = chunk.length;
                            state.chunks[indx] = chunk;
                          })
                        );
                        setTimeout(() =>
                          this.setState((state) => {
                            let chunk = true;
                            const isLoadingChunks = (state.isLoadingChunks[
                              indx
                            ] = chunk);
                            return isLoadingChunks;
                          })
                        );
                      });
                    }
                  });

                this.deep = false;
              }

              this.preFetch = async (dir) => {
                let req = [];
                types.forEach((t, indx) => {
                  req[indx] = client.query({
                    query: currentStation,
                    variables: {
                      token: variables.token,
                      stationId: variables.stationId,
                      typeName:
                        indx == 2 ? `${zoomsvar[this.state.zoom]}${t}` : t,
                      since: moment(variables.dataSince)
                        .add(dir, "d")
                        .format("YYYY-MM-DDTHH:mm"),
                      to: moment(variables.dataTo)
                        .add(dir, "d")
                        .format("YYYY-MM-DDTHH:mm"),
                      maxPoints:
                        indx == 4
                          ? this.props.maxPoints / 10
                          : this.props.maxPoints,
                    },
                  });
                  setTimeout(() =>
                    this.setState((state) => {
                      let chunk = false;
                      const isLoadingChunks = (state.isLoadingChunks[
                        indx
                      ] = chunk);
                      return isLoadingChunks;
                    })
                  );
                  if (indx == 4)
                    Promise.all([req[0], req[4]]).then((data) => {
                      let filtredData = data[0].data.amsPlotData.map(
                        (d) => d[1]
                      );
                      let minmax = [
                        Math.min(...filtredData),
                        Math.max(...filtredData),
                      ];

                      setTimeout(() =>
                        this.setState((state) => {
                          let chunk = this.dataTransformer(
                            data[1],
                            indx,
                            minmax
                          );
                          if (dir == -1)
                            state.chunks[indx] = [
                              ...chunk,
                              ...state.chunks[indx].slice(
                                0,
                                this.state.chunksLength[indx]
                              ),
                            ];
                          if (dir == 1)
                            state.chunks[indx] = [
                              ...state.chunks[indx].slice(
                                state.chunks[indx].length -
                                  this.state.chunksLength[indx],
                                state.chunks[indx].length
                              ),
                              ...chunk,
                            ];

                          state.chunksLength[indx] = chunk.length;
                        })
                      );
                      setTimeout(() =>
                        this.setState((state) => {
                          let chunk = true;
                          const isLoadingChunks = (state.isLoadingChunks[
                            indx
                          ] = chunk);
                          return isLoadingChunks;
                        })
                      );
                    });
                  else {
                    req[indx].then((data) => {
                      setTimeout(() =>
                        this.setState((state) => {
                          let chunk = this.dataTransformer(data, indx);
                          if (dir == -1)
                            state.chunks[indx] = [
                              ...chunk,
                              ...state.chunks[indx].slice(
                                0,
                                this.state.chunksLength[indx]
                              ),
                            ];
                          if (dir == 1)
                            state.chunks[indx] = [
                              ...state.chunks[indx].slice(
                                state.chunks[indx].length -
                                  this.state.chunksLength[indx],
                                state.chunks[indx].length
                              ),
                              ...chunk,
                            ];

                          state.chunksLength[indx] = chunk.length;
                        })
                      );
                      setTimeout(() =>
                        this.setState((state) => {
                          let chunk = true;
                          const isLoadingChunks = (state.isLoadingChunks[
                            indx
                          ] = chunk);
                          return isLoadingChunks;
                        })
                      );
                    });
                  }
                });
                this.setState({
                  dataGap: moment(this.state.dataGap)
                    .add(dir, "d")
                    .format("YYYY-MM-DDTHH:mm"),
                });
                this.deepDarkFantasy = true;
              };

              return null;
            }}
          </Query>

          <AmsChart
            opacity={this.props.opacity}
            superArr={superArr}
            plotHeight={this.props.height}
            dateFrom={variables.since}
            dateTo={variables.to}
            isAdmin={this.props.isAdmin}
            animated={this.props.animated}
            // arrows={true}
          />
          <div
            style={{
              marginTop: "-40px",
              width: "100px",
            }}
          >
            {!this.props.isAdmin && (
              <Select
                theme={(theme) => ({
                  ...theme,
                  borderRadius: 1,
                  spacing: {
                    baseUnit: 2,
                    controlHeight: 30,
                    menuGutter: 2,
                  },
                  colors: {
                    ...theme.colors,
                    primary: "#cee0eb",
                    neutral0: "#000000",
                  },
                })}
                isSearchable={false}
                // opacity={10}
                onChange={(option) =>
                  this.state.zoom !== option.value
                    ? (this.setState({ zoom: option.value }),
                      (this.deep = true))
                    : ""
                }
                placeholder={""}
                value={selectValues[this.state.zoom]}
                menuPlacement="top"
                menuPosition="fixed"
                styles={selecterStyle}
                options={selectValues}
              />
            )}
          </div>
        </div>
      </ApolloProvider>
    );
  }
}

export default AmsChartGen;
