import { FontIcon } from "@sc/components/ui";
import _ from "lodash";
import React, { Component } from "react";

export class UpDownControls extends Component {
  constructor(props) {
    super(props);
    this.moveCampaignObject = this.moveCampaignObject.bind(this);
  }

  async moveCampaignObject(direction = "DOWN") {
    const {
      id,
      useObjects,
      updateCampaignObjectMutation,
      setLoading
    } = this.props;

    setLoading(true);
    // 1. get object content of obj1
    console.log("1. get object content of obj1");
    const key1 = _.findIndex(useObjects, itm => itm.id === id);
    const obj1 = _.get(useObjects, key1, false);

    // 2. get object content of obj2
    console.log("2. get object content of obj2");
    const key2 = direction === "DOWN" ? key1 + 1 : key1 - 1;
    const obj2 = _.get(useObjects, key2, false);
    console.log("Original Objs", { obj1, obj2 });

    // 3. swap x, y positions of each
    const newObjXY1 = _.has(obj2, "x")
      ? { ...obj1, x: obj2.x, y: obj2.y }
      : false;
    const newObjXY2 = _.has(obj1, "x")
      ? { ...obj2, x: obj1.x, y: obj1.y }
      : false;
    console.log("3. Swapped X,Y positions", { newObjXY1, newObjXY2 });
    // update useObjects;
    const newUseObjects1 = [
      ...useObjects.slice(0, key1),
      newObjXY1,
      ...useObjects.slice(key1 + 1)
    ];
    const newUseObjects2 = [
      ...newUseObjects1.slice(0, key2),
      newObjXY2,
      ...newUseObjects1.slice(key2 + 1)
    ];

    // 4. make connectToIds of obj1 = connectToIds of obj2 (minus itself)
    console.log({ newUseObjects1, newUseObjects2 });
    const obj1ConnectToIds = _.map(obj1.connectTo, itm => itm.id);
    const obj2ConnectToIds = _.map(obj2.connectTo, itm => itm.id);
    console.log("ConnectionIds", { obj1ConnectToIds, obj2ConnectToIds });

    const connectToIds1 =
      direction === "DOWN"
        ? _.map(
            _.filter(obj2ConnectToIds, obj => obj.id !== newObjXY1.id),
            itm => ({ id: itm })
          )
        : [{ id: newObjXY2.id }];

    const toDisconnect1 = _.filter(
      obj1ConnectToIds,
      itm => _.findIndex(connectToIds1, newItm => itm.id === newItm.id) === -1
    );

    const newObj1ConnectToIds = {
      ..._.omit(newObjXY1, ["connectTo", "page"]),
      connectToIds: connectToIds1,
      disconnectIds: toDisconnect1.length
        ? toDisconnect1.map(obj => ({ id: obj }))
        : [],
      deleted: false
    };

    // 5. make connectToIds of obj2 = connectToIds of obj1 (minus itself)
    const connectToIds2 =
      direction === "UP"
        ? _.map(
            _.filter(obj1ConnectToIds, obj => obj.id !== newObjXY2.id),
            itm => ({ id: itm })
          )
        : [{ id: newObjXY1.id }];

    const toDisconnect2 = _.filter(
      obj2ConnectToIds,
      itm => _.findIndex(connectToIds2, newItm => itm.id === newItm.id) === -1
    );

    const newObj2ConnectToIds = {
      ..._.omit(newObjXY2, ["connectTo", "page"]),
      connectToIds: connectToIds2,
      disconnectIds: toDisconnect2.length
        ? toDisconnect2.map(obj => ({ id: obj }))
        : [],
      deleted: false
    };

    console.log({ toDisconnect1, toDisconnect2 });

    console.log({ newObj1ConnectToIds, newObj2ConnectToIds });
    await updateCampaignObjectMutation({ variables: newObj1ConnectToIds });
    await updateCampaignObjectMutation({ variables: newObj2ConnectToIds });

    // 6. make anything that was connected to obj 2 now connect to obj 1
    const objsConnectedToObj2 = _.filter(
      newUseObjects2,
      itm => _.findIndex(itm.connectTo, obj => obj.id === obj2.id) > -1
    );
    console.log({ objsConnectedToObj2 });

    _.forEach(objsConnectedToObj2, async itm => {
      // get the object (itm)
      const obj = _.omit(itm, ["connectTo", "page"]);
      const ids = [..._.map(itm.connectTo, itm => itm.id), obj1.id]; // only id
      const existingIds =
        itm.id === newObj1ConnectToIds.id
          ? newObj1ConnectToIds.connectToIds.map(itm => itm.id) // was in [{id: xyz}] format
          : [];

      const connectToIds = _.filter(
        [...ids, ...existingIds],
        id => id !== itm.id && id !== obj2.id
      ).map(itm => ({ id: itm }));
      const toDisconnect = _.filter(
        obj.connectTo,
        itm =>
          _.findIndex(connectToIds, newItem => itm.id === newItem.id) === -1
      );
      const disconnectIds = toDisconnect.length
        ? toDisconnect.map(obj => ({ id: obj.id }))
        : [];

      await updateCampaignObjectMutation({
        variables: {
          ...obj,
          connectToIds,
          disconnectIds,
          deleted: false
        }
      });
      console.log({
        variables: { ...obj, connectToIds, disconnectIds, deleted: false }
      });
    });

    // 7. make anything that was connected to obj 1 now connect to obj 2
    const objsConnectedToObj1 = _.filter(
      newUseObjects2,
      itm => _.findIndex(itm.connectTo, obj => obj.id === obj1.id) > -1
    );
    console.log({ objsConnectedToObj1 });
    _.forEach(objsConnectedToObj1, async itm => {
      // get the object (itm)
      const obj = _.omit(itm, ["connectTo", "page"]);
      const ids = [..._.map(itm.connectTo, itm => itm.id), obj2.id]; // only id
      const existingIds =
        itm.id === newObj2ConnectToIds.id
          ? newObj2ConnectToIds.connectToIds.map(itm => itm.id) // was in [{ id: xyz }] format
          : [];
      const connectToIds = _.filter(
        [...ids, ...existingIds],
        id => id !== itm.id && id !== obj1.id
      ).map(itm => ({ id: itm }));
      const toDisconnect = _.filter(
        obj.connectTo,
        itm =>
          _.findIndex(connectToIds, newItem => itm.id === newItem.id) === -1
      );
      const disconnectIds = toDisconnect.length
        ? toDisconnect.map(obj => ({ id: obj.id }))
        : [];

      await updateCampaignObjectMutation({
        variables: {
          ...obj,
          connectToIds,
          disconnectIds,
          deleted: false
        }
      });
      console.log({
        variables: { ...obj, connectToIds, disconnectIds, deleted: false }
      });
    });

    // 8. refresh the page
    window.location.reload();
  }

  async xmoveCampaignObject(direction = "DOWN") {
    const {
      id,
      useObjects,
      updateCampaignObjectMutation,
      setLoading
    } = this.props;

    setLoading(true);

    console.log({ useObjects });
    // 1. get object content of obj1
    console.log("1. get object content of obj1");
    const key1 = _.findIndex(useObjects, itm => itm.id === id);
    const obj1 = _.get(useObjects, key1, false);

    // 2. get object content of obj2
    console.log("2. get object content of obj2");
    const key2 = direction === "DOWN" ? key1 + 1 : key1 - 1;
    const obj2 = _.get(useObjects, key2, false);
    console.log("Original Objs", { obj1, obj2 });

    // 3. swap x, y positions of each
    const newObjXY1 = _.has(obj2, "x")
      ? { ...obj1, x: obj2.x, y: obj2.y }
      : false;
    const newObjXY2 = _.has(obj1, "x")
      ? { ...obj2, x: obj1.x, y: obj1.y }
      : false;
    console.log("3. Swapped X,Y positions", { newObjXY1, newObjXY2 });
    // update useObjects;
    const newUseObjects1 = [
      ...useObjects.slice(0, key1),
      newObjXY1,
      ...useObjects.slice(key1 + 1)
    ];
    const newUseObjects2 = [
      ...newUseObjects1.slice(0, key2),
      newObjXY2,
      ...newUseObjects1.slice(key2 + 1)
    ];

    // 4. make connectToIds of obj1 = connectToIds of obj2 (minus itself)
    const obj1ConnectToIds = _.map(obj1.connectTo, itm => itm.id);
    const obj2ConnectToIds = _.map(obj2.connectTo, itm => itm.id);
    console.log("ConnectionIds", { obj1ConnectToIds, obj2ConnectToIds });
    const newObj1ConnectToIds =
      direction === "DOWN"
        ? {
            ..._.omit(newObjXY1, ["connectTo", "page"]),
            connectToIds: _.filter(
              obj2ConnectToIds,
              obj => obj.id !== newObjXY1.id
            ),
            deleted: false
          }
        : {
            ..._.omit(newObjXY1, ["connectTo", "page"]),
            connectToIds: [newObjXY2.id],
            deleted: false
          };
    console.log(
      "4. make connectToIds of obj1 = connectToIds of obj2 (minus itself)",
      { newObj1ConnectToIds }
    );

    // 5. make connectToIds of obj2 = connectToIds of obj1 (minus itself)
    const newObj2ConnectToIds =
      direction === "UP"
        ? {
            ..._.omit(newObjXY2, ["connectTo", "page"]),
            connectToIds: _.filter(
              obj1ConnectToIds,
              obj => obj.id !== newObjXY2.id
            ),
            deleted: false
          }
        : {
            ..._.omit(newObjXY2, ["connectTo", "page"]),
            connectToIds: [newObjXY1.id],
            deleted: false
          };
    console.log("5. make connecToIds of obj2 connect to obj1 (minus itself)", {
      newObj2ConnectToIds
    });
    await updateCampaignObjectMutation({ variables: newObj1ConnectToIds });
    await updateCampaignObjectMutation({ variables: newObj2ConnectToIds });
    console.log({ variables: newObj1ConnectToIds });
    console.log({ variables: newObj2ConnectToIds });

    // 7. make anything that was connected to obj 2 now connect to obj 1
    // who is connected to obj 2
    const objsConnectedToObj2 = _.filter(
      newUseObjects2,
      itm => _.findIndex(itm.connectTo, obj => obj.id === obj2.id) > -1
    );
    console.log({ objsConnectedToObj2 });
    _.forEach(objsConnectedToObj2, async itm => {
      // get the object (itm)
      const obj = _.omit(itm, ["connectTo", "page"]);
      const ids = [..._.map(itm.connectTo, itm => itm.id), obj1.id];
      const existingIds =
        itm.id === newObj1ConnectToIds.id
          ? newObj1ConnectToIds.connectToIds
          : [];
      const connectToIds = _.filter(
        [...ids, ...existingIds],
        id => id !== itm.id && id !== obj2.id
      );
      await updateCampaignObjectMutation({
        variables: {
          ...obj,
          connectToIds,
          deleted: false
        }
      });
      console.log({ variables: { ...obj, connectToIds, deleted: false } });
    });

    // 8. make anything that was connected to obj 1 now connect to obj 2
    // who is connected to obj 1
    const objsConnectedToObj1 = _.filter(
      newUseObjects2,
      itm => _.findIndex(itm.connectTo, obj => obj.id === obj1.id) > -1
    );
    console.log({ objsConnectedToObj1 });
    _.forEach(objsConnectedToObj1, async itm => {
      // get the object (itm)
      const obj = _.omit(itm, ["connectTo", "page"]);
      const ids = [..._.map(itm.connectTo, itm => itm.id), obj2.id];
      const existingIds =
        itm.id === newObj2ConnectToIds.id
          ? newObj2ConnectToIds.connectToIds
          : [];
      const connectToIds = _.filter(
        [...ids, ...existingIds],
        id => id !== itm.id && id !== obj1.id
      );
      await updateCampaignObjectMutation({
        variables: {
          ...obj,
          connectToIds,
          deleted: false
        }
      });
      console.log({ variables: { ...obj, connectToIds, deleted: false } });
    });

    // refetch everything
    window.location.reload();
  }

  render() {
    return (
      <div style={{ position: "absolute", zIndex: 2, marginLeft: 2 }}>
        {this.props.showUp && (
          <div
            onClick={() => this.moveCampaignObject("UP")}
            style={{ marginTop: -45, cursor: "pointer" }}
          >
            <FontIcon style={{ zoom: 2 }}>arrow_drop_up</FontIcon>
          </div>
        )}

        {this.props.showDown && (
          <div
            onClick={() => this.moveCampaignObject("DOWN")}
            style={{ marginTop: 40, cursor: "pointer" }}
          >
            <FontIcon style={{ zoom: 2 }}>arrow_drop_down</FontIcon>
          </div>
        )}
      </div>
    );
  }
}
