import { Toolbar } from "@sc/components/ui";
import theme from "@sc/components/ui/theme";
import { AppConfig } from "@sc/modules/app";
import _ from "lodash";
import React, { Component } from "react";
import WebFont from "webfontloader";
// import { app } from "../../config";
import AppDrawer from "../appdrawer";
import { RenamableTitle, style } from "../campaign/shared";
import Builder from "./Builder";
import { leftActionsGroup, rightActionsGroup } from "./HeaderComponents";
import PublishSuccessPopup from "./PublishSuccess";
import SEO from "./SEO";
import { EmailSettings, MerchantSettings } from "./Settings";
import TabSidebar from "./TabSidebar";
import Templates from "./Templates";
import Tracking from "./Tracking";
import CSS from "./CSS";
import ExitIntent from "./ExitIntent";
import History from "./History";

const CURSOR_ID = 1111;
const standardCursor = {
  type: "Cursor",
  id: CURSOR_ID,
  className: false,
  html: "",
  parent: false,
  properties: false,
};

var saveTimeout = null;

class Canvas extends Component {
  constructor(props) {
    super(props);
    this.state = {
      appDrawerVisible: false,
      settings: false,
      content: [],
      showPublish: false,
      state: {
        active: false,
        hover: false,
      },
      undoStack: [],
      undoPosition: 0,
      mobileState: _.get(props, "defaultMobileState", {
        type: props.show === "builder" ? "fullscreen" : "desktop",
        dimensions:
          props.show === "builder"
            ? {
                width: "100%",
                minHeight: "100vh",
                margin: 0,
                marginTop: 57,
              }
            : {
                maxWidth: 1000,
                width: "100%",
                minHeight: "70vh",
                margin: "80px auto",
                overflow: "hidden",
              },
      }),
      activePropertyWindows: [],
      savingStatus: "SAVED",
      canDrag: true,
    };

    this.ancestors = [];

    this.setActiveObject = this.setActiveObject.bind(this);
    this.toggleAppDrawer = this.toggleAppDrawer.bind(this);

    // page edit methods
    this.addThisAfterThat = this.addThisAfterThat.bind(this);
    this.removeItem = this.removeItem.bind(this);
    this.duplicateItem = this.duplicateItem.bind(this);
    this.moveThisByThat = this.moveThisByThat.bind(this);
    this.addHoverCursor = this.addHoverCursor.bind(this);
    // this.resetState = this.resetState.bind(this);
    this.changeState = this.changeState.bind(this);
    this.renderFromState = this.renderFromState.bind(this);
    this.updateContent = this.updateContent.bind(this);
    this.updateComponentSettings = this.updateComponentSettings.bind(this);
    this.updateComponentStyle = this.updateComponentStyle.bind(this);
    this.listAncestors = this.listAncestors.bind(this);
    this.doUndoRedo = this.doUndoRedo.bind(this);
    this.setMobileState = this.setMobileState.bind(this);
    this.getMobileState = this.getMobileState.bind(this);
    this.setActivePropertyWindows = this.setActivePropertyWindows.bind(this);
    this.getActivePropertyWindows = this.getActivePropertyWindows.bind(this);
    this.setCanDrag = this.setCanDrag.bind(this);
    this.getCanDrag = this.getCanDrag.bind(this);
  }

  static contextType = AppConfig;

  async componentDidMount() {
    const { match, getPageQuery } = this.props;

    const { data } = await getPageQuery.refetch({ id: match.params.nodeId });

    const { page } = data;

    if (!page) window.location.href = "/login";
    else {
      this.setState(
        {
          content: page.content,
          undoStack: [page.content],
          name: page.name,
          id: page.id,
        },
        () => {
          // Load Web Fonts
          const { content } = this.state;
          const fontObjs = _.filter(content, (itm) =>
            _.has(itm, "properties.fontFamily")
          );
          const families = _.uniq(
            _.map(fontObjs, (itm) => itm.properties.fontFamily)
          );
          if (families.length) {
            console.log({ families });
            WebFont.load({ google: { families } });
          }
        }
      );
    }
  }

  componentWillUnmount() {
    cancelAnimationFrame(this.requestedFrame);
    console.log("Animation Frame was Canceled");
  }

  toggleAppDrawer() {
    this.setState((prevState) => ({
      appDrawerVisible: !prevState.appDrawerVisible,
    }));
    return null;
  }

  setActiveObject(settings) {
    // if (_.has(this.props, "onSetActiveObject"))
    //   this.props.onSetActiveObject(settings);
    this.setState({ settings });
    return settings;
  }

  scheduleUpdate(updateFn, callbackFn = () => null) {
    // if (_.has(this.props, "onScheduleUpdate"))
    //   this.props.onScheduleUpdate(updateFn, callbackFn);
    this.pendingUpdateFn = [updateFn, callbackFn];

    if (!this.requestedFrame) {
      this.requestedFrame = requestAnimationFrame(this.renderFromState);
    }
  }

  changeState(id, state = "normal", callbackFn = () => false) {
    // console.log('Changing state', id, state);
    if (_.has(this.props, "onChangeState"))
      this.props.onChangeState(id, state, this.state.content);

    if (!id) return;

    const prevContent = this.state.content;

    // 0. find the location in the array where this item is
    const key = prevContent.findIndex((itm) => itm.id === id);

    if (key === -1) return;

    // 1. remove the state field for all items in the content arrray with that state
    const content = prevContent.map((itm) => ({
      ...itm,
      state: itm.state === state ? "normal" : itm.state,
    }));

    // 2. reconstruct the content array, but modify the state of the specific object
    const updatedContent = [
      ...content.slice(0, key),
      { ...content[key], state },
      ...content.slice(key + 1),
    ];

    if (state === "hover" && prevContent[key].state === "active") return;
    if (state === "normal" && prevContent[key].state === "active") return;

    // 3. remove any cursor still showing
    const contentWithNoCursors = updatedContent.filter(
      (itm) => itm.id !== CURSOR_ID
    );

    // 4. update the state with the reconstructed content array
    this.scheduleUpdate({ content: contentWithNoCursors }, callbackFn);
  }

  recursivelyAddThisAfterThat(newItem, afterId, content) {
    // 1. Get the position of the 'afterId' item
    const key = content.findIndex((itm) => itm.id === afterId);

    // 2. Remove any children from the new Item
    const { children, ...newItemWithoutChildren } = newItem;

    // 3. Generate a new Id for the new item
    const id = Math.random()
      .toString(36)
      .slice(2);

    // 4. Add the childless item to the content array that you will return for db updating
    this.addedContent = [
      ...content.slice(0, key + 1),
      {
        ...newItemWithoutChildren,
        id,
      },
      ...content.slice(key + 1),
    ];

    // 5. Add any child items if there is any
    if (newItem.hasOwnProperty("children")) {
      // Loop through each child object
      const children = [..._.get(newItem, "children", [])].reverse();
      children.forEach((itm) => {
        // Set the previously generated id as the child object's parent
        const updatedItm = { ...itm, parent: id };
        // Call the recursive function to update the added content array with our child object
        // ...or handle any children that my new item has
        this.addedContent = this.recursivelyAddThisAfterThat(
          updatedItm,
          id,
          this.addedContent
        );
      });
    }

    // console.log("after children update", id, this.addedContent);
    this.changeState(id, "active");

    // 6. Return the updated content array
    return this.addedContent;
  }

  addThisAfterThat(item, id, callbackFn = () => false) {
    // if (_.has(this.props, "onAddThisAfterThat"))
    //   this.props.onAddThisAfterThat(item, id, callbackFn);
    if (!id) return;
    // Get content item
    const prevContent = this.state.content;

    // Establish parent for new item
    const object = prevContent.filter((itm) => itm.id === id);
    if (!object.length) return;

    const itemWithParent = {
      ...item,
      parent: object[0].parent,
      state: "active",
    };
    console.log({ object, itemWithParent });

    // Call recursive function to build a chain of items to add
    // as decendents of this object
    const theContent = this.recursivelyAddThisAfterThat(
      itemWithParent,
      id,
      prevContent
    );
    const content = theContent.filter((itm) => itm.id !== CURSOR_ID);

    // Now update the document with all the new items
    this.setState(
      {
        content,
      },
      () => {
        // console.log("Add This After That", { content });

        this.handleUpdatePageContent(
          content,
          true,
          () => callbackFn(content),
          false
        );
      }
    );
  }

  recursivelyRemoveItem(id, content) {
    this.removedContent = content.filter((itm) => itm.id !== id); // everything without item
    this.removedContent
      .filter((itm) => itm.parent === id)
      .forEach((itm) => {
        this.removedContent = this.recursivelyRemoveItem(
          itm.id,
          this.removedContent
        );
      });

    return this.removedContent;
  }

  removeItem(id, dbUpdate = true) {
    // if (_.has(this.props, "onRemoveItem"))
    //   this.props.onRemoveItem(id, dbUpdate);
    const prevContent = this.state.content;
    const key = prevContent.findIndex((itm) => itm.id === id);
    if (prevContent[key].parent) {
      const content = this.recursivelyRemoveItem(id, prevContent);

      this.setState(
        {
          content,
        },
        () => {
          // persist the state change to the database
          if (dbUpdate) this.handleUpdatePageContent(content);
        }
      );
    } else {
      alert("You cannot remove the main body object on this page");
    }
  }

  recursivelyDuplicate(id, content, parent) {
    // 1. Get Object

    // 2. Get its direct children
    const children = content.filter((itm) => itm.parent === id);

    // 3. Loop through each child
    children.forEach((child) => {
      // 4. Add a modified object to the class level array
      const newId = Math.random()
        .toString(36)
        .slice(2);

      this.duplicatedItemCollection = [
        ...this.duplicatedItemCollection,
        { ...child, state: "normal", id: newId, parent },
      ];

      // 5. Call recursivelyDuplicate on child object
      this.recursivelyDuplicate(child.id, content, newId);
    });

    // 6. Return the class level array so that it can be added to state
    return this.duplicatedItemCollection;
  }

  duplicateItem(
    id,
    doRecursive = true,
    dbUpdate = true,
    callbackFn = () => false
  ) {
    // if (_.has(this.props, "onDuplicateItem"))
    //   this.props.onDuplicateItem(id, doRecursive, dbUpdate, callbackFn);
    const prevContent = this.state.content;

    // get the key of the id
    const key = prevContent.findIndex((itm) => itm.id === id);
    const newId = Math.random()
      .toString(36)
      .slice(2);

    // create a duplicate version of the item, but only modify the id
    const originalItem = { ...prevContent[key], state: "normal", id: newId };
    this.duplicatedItemCollection = [originalItem];

    const duplicateItem = doRecursive
      ? this.recursivelyDuplicate(id, prevContent, newId)
      : [originalItem];

    const content = [
      ...prevContent.slice(0, key + 1),
      ...duplicateItem,
      ...prevContent.slice(key + 1),
    ];

    // generate a new array with the item twice
    this.setState(
      {
        content,
      },
      () => {
        this.changeState(newId, "active");
        // persist the state change to the database
        if (dbUpdate) this.handleUpdatePageContent(content);
        callbackFn();
      }
    );
  }

  moveThisByThat(id1, id2, dbUpdate = true) {
    console.log("moveThisByThat", id1, id2);
    // if (_.has(this.props, "onMoveThisByThat"))
    //   this.props.onMoveThisByThat(id1, id2, dbUpdate);

    if (id1 === id2) return; // cancel if they're the same

    const prevContent = this.state.content;

    const keyOfId1 = prevContent.findIndex((itm) => itm.id === id1);
    const keyOfId2 = prevContent.findIndex((itm) => itm.id === id2);
    const id1Content = prevContent[keyOfId1];

    if (keyOfId2 === -1) return; // cancel if the second id doesn't exist

    // remove id1
    const contentAfterRemoveItem = [
      ...prevContent.slice(0, keyOfId1),
      ...prevContent.slice(keyOfId1 + 1),
    ];

    // add id1 under id2 and return result
    const parent = keyOfId2 > -1 ? prevContent[keyOfId2].parent : false;
    const revisedItem = { ...id1Content, parent, state: "active" };

    const content = [
      ...contentAfterRemoveItem.slice(0, keyOfId2),
      revisedItem,
      ...contentAfterRemoveItem.slice(keyOfId2),
    ];

    // now remove the cursor (if any)
    const contentWithoutCursor = content.filter((itm) => itm.id !== CURSOR_ID);

    this.setState(
      {
        content: contentWithoutCursor,
      },
      () => {
        // persist the state change to the database
        this.changeState(id1, "active", () => {
          if (dbUpdate) this.handleUpdatePageContent(contentWithoutCursor);
        });
      }
    );
  }

  addHoverCursor(id, addType = "after") {
    if (!id) return;

    const prevContent = this.state.content;

    // 1. Remove all existing cursors
    const contentWithNoCursors = prevContent.filter(
      (itm) => itm.id !== CURSOR_ID
    );

    // 2. Find the location of the array where this item is
    const key = contentWithNoCursors.findIndex((itm) => itm.id === id);
    if (key === -1) return;

    const i = addType === "after" ? 1 : 0;

    // 3. Stop if there is already a cursor in the location i want
    // if (prevContent.hasOwnProperty(key + i)) {
    //   console.log("Adding Cursor", addType, prevContent[key + i].id);
    //   if (prevContent[key + i].id === CURSOR_ID) return;
    // }

    // 4. Add the cursor in correct position
    const cursorParent =
      addType === "inside" ? id : contentWithNoCursors[key].parent;
    const cursorContent = { ...standardCursor, parent: cursorParent };

    // 5. Change the state of the parent container to be a hover state
    let contentWithParentHover = contentWithNoCursors;
    if (cursorParent) {
      const cursorParentKey = contentWithNoCursors.findIndex(
        (itm) => itm.id === cursorParent
      );
      const parentContent = contentWithNoCursors[cursorParentKey];

      // a. remove the state field for all items in the content array with that state
      const noHoverStateContent = contentWithNoCursors.map((itm) => {
        const { state, ...stateRemoved } = itm;
        return stateRemoved;
      });

      // b. reconstruct the content array, but modify the state of the specific object
      contentWithParentHover = [
        ...noHoverStateContent.slice(0, cursorParentKey),
        { ...parentContent, state: "hover" },
        ...noHoverStateContent.slice(cursorParentKey + 1),
      ];
    }

    // 6. update the state
    const content = contentWithParentHover;

    this.scheduleUpdate({
      content: [
        ...content.slice(0, key + i),
        cursorContent,
        ...content.slice(key + i),
      ],
    });
  }

  updateComponentSettings(
    id,
    settings,
    dbUpdate = true,
    debounceTimeout = 500
  ) {
    // console.log("TESTING!?!");
    // delete settings["state"];
    // if (_.has(this.props, "onUpdateComponentSettings"))
    //   this.props.onUpdateComponentSettings(
    //     id,
    //     settings,
    //     dbUpdate,
    //     debounceTimeout
    //   );

    // get the key of the id
    const key = this.state.content.findIndex((itm) => itm.id === id);

    // get current state
    // const currentSettings = _.get(this.state, `content[${key}]`);
    // const state = _.get(this.state, `content[${key}].state`);
    // console.log({ currentSettings, state });

    const content = [
      ...this.state.content.slice(0, key),
      {
        ...settings,
        state: _.get(this.state, `content[${key}].state`, "normal"),
      },
      ...this.state.content.slice(key + 1),
    ];

    this.setState({ content }, () => {
      // console.log({ settings, content: this.state.content });
      if (dbUpdate) {
        console.log("Saved, now updating db", settings);
        this.handleUpdatePageContent(
          content,
          true,
          () => false,
          debounceTimeout
        );
      }
    });
  }

  updateComponentStyle(id, newStyle, dbUpdate = true, debounceTimeout = 500) {
    // if (_.has(this.props, "onUpdateComponentStyle"))
    //   this.props.onUpdateComponentStyle(
    //     id,
    //     newStyle,
    //     dbUpdate,
    //     debounceTimeout
    //   );
    const prevContent = this.state.content;

    // get the settings object of the id
    const key = prevContent.findIndex((itm) => itm.id === id);
    const theSettings = prevContent[key];

    // mobile properties
    let mobileProperties;
    let desktopProperties,
      tabletProperties,
      smartphoneProperties,
      fullscreenProperties;
    if (theSettings.properties.hasOwnProperty("mobile")) {
      if (theSettings.properties.mobile) {
        const cmp = theSettings.properties.mobile;
        desktopProperties = cmp.hasOwnProperty("desktop") ? cmp.desktop : {};
        tabletProperties = cmp.hasOwnProperty("tablet") ? cmp.tablet : {};
        smartphoneProperties = cmp.hasOwnProperty("smartphone")
          ? cmp.smartphone
          : {};
        fullscreenProperties = cmp.hasOwnProperty("fullscreen")
          ? cmp.fullscreen
          : {};
      }
    }

    const mstate = this.state.mobileState.type;
    if (mstate === "fullscreen") {
      mobileProperties = {
        fullscreen: { ...fullscreenProperties, ...newStyle },
      };
    }
    if (mstate === "desktop") {
      mobileProperties = { desktop: { ...desktopProperties, ...newStyle } };
    }
    if (mstate === "tablet") {
      mobileProperties = { tablet: { ...tabletProperties, ...newStyle } };
    }
    if (mstate === "smartphone") {
      mobileProperties = {
        smartphone: { ...smartphoneProperties, ...newStyle },
      };
    }

    const theStyle =
      mstate === "tablet" || mstate === "smartphone" ? {} : newStyle;

    const updatedSettingsObj = {
      ...theSettings,
      properties: {
        ...theSettings.properties,
        mobile: {
          ...theSettings.properties.mobile,
          ...mobileProperties,
        },
        ...theStyle,
      },
    };

    this.updateComponentSettings(
      id,
      updatedSettingsObj,
      dbUpdate,
      debounceTimeout
    );
  }

  updateContent(
    content,
    dbUpdate = true,
    debounceTimeout = 500,
    callbackFn = () => false
  ) {
    // if (_.has(this.props, "onUpdateContent"))
    //   this.props.onUpdateContent(item, id, callbackFn);

    this.setState({ content }, () => {
      if (dbUpdate) {
        this.handleUpdatePageContent(
          content,
          true,
          callbackFn,
          debounceTimeout
        );
      }
    });
  }

  generateAncestors(content, id) {
    const i = content.findIndex((c) => c.id === id);
    if (i > -1) {
      const parent = content[i].parent;
      this.ancestors = [...this.ancestors, content[i]];
      if (parent) this.generateAncestors(content, parent);
      return this.ancestors;
    }
    return false;
  }

  listAncestors(content, id) {
    if (!id) return;
    const ancestors = this.generateAncestors(content, id);
    this.ancestors = [];
    return ancestors;
  }

  listComponents(content = [], filterOut = [], filterOnly = []) {
    // if (_.get(this.props, "onListComponents", false))
    // this.props.onListComponents(content, filterOut, filterOnly);

    const iconMap = {
      Container: "select_all",
      Columns: "view_column",
      Collection: "format_list_numbered",
      p: "text_fields",
      Paragraph: "text_fields",
      Video: "play_circle_outline",
      Picture: "image",
      Headline: "title",
      Button: "crop_16_9",
      TextInput: "input",
      Popup: "aspect_ratio",
    };

    const filteredList = _.filter(content, (obj) => {
      return _.findIndex(filterOut, (i) => obj[i[0]] === i[1]) === -1;
    });

    const showOnly = _.filter(filteredList, (obj) => {
      if (filterOnly.length)
        return _.findIndex(filterOnly, (i) => obj[i[0]] === i[1]) > -1;
      return true;
    });

    return _.map(showOnly, (obj) => {
      const name = _.get(obj, "name", obj.type);
      let html = _.has(obj, "html")
        ? obj.html.replace(/<(?:.|\n)*?>/gm, "")
        : name;

      if (_.has(obj, "placeholder"))
        html = obj.placeholder.replace(/<(?:.|\n)*?>/gm, "");

      return {
        id: obj.id,
        icon: _.get(iconMap, obj.type, "widgets"),
        html: _.get(obj, "label", html),
        settings: obj,
      };
    });
  }

  pageSubscriptionUpdate = (previousState, { subscriptionData }) => {
    if (subscriptionData.data.page.mutation === "UPDATED") {
      console.log("subscriptionData", subscriptionData);
      this.setState(
        {
          content: subscriptionData.data.page.node.content,
        },
        () => console.log(this.state.content)
      );
    }

    return subscriptionData.data.page.node;
  };

  doUndoRedo(type) {
    console.log("Doing an Undo/Redo", type);
    // if (_.has(this.props, "onDoUndoRedo")) this.props.onDoUndoRedo(type);

    this.setState(
      (prevContent) => {
        const { undoStack, undoPosition } = prevContent;
        const key = type === "undo" ? undoPosition - 1 : undoPosition + 1;

        if (undoStack.hasOwnProperty(key)) {
          return {
            ...prevContent,
            content: undoStack[key],
            undoPosition: key,
          };
        }
        return prevContent;
      },
      () => this.handleUpdatePageContent(this.state.content, false)
    );
  }

  setMobileState(type, dimensions, backgroundImage = false) {
    // if (_.has(this.props, "onSetMobileState"))
    // this.props.onSetMobileState(type, dimensions, backgroundImage);
    this.setState(
      {
        mobileState: {
          type,
          dimensions,
        },
      },
      () => {
        // force a rerender otherwise the content will overlap the mobile viewport
        this.changeState(this.state.content[0].id, this.state.content[0].state);
      }
    );
  }

  getMobileState() {
    // if (_.has(this.props, "onGetMobileState")) this.props.onGetMobileState();
    return this.state.mobileState;
  }

  setActivePropertyWindows(activePropertyWindows, callbackFn = () => false) {
    // if (_.has(this.props, "onActivePropertyWindows"))
    //   this.props.onActivePropertyWindows(activePropertyWindows, callbackFn);
    this.setState({ activePropertyWindows }, callbackFn);
  }

  getActivePropertyWindows() {
    // if (_.has(this.props, "onGetActivePropertyWindows"))
    //   this.props.onGetActivePropertyWindows();
    return this.state.activePropertyWindows;
  }

  debounce = (func, wait) => {
    if (!saveTimeout) {
      clearTimeout(saveTimeout);

      saveTimeout = setTimeout(() => {
        saveTimeout = null;
        // func.apply(this, arguments);
        func();
      }, wait);
    }
  };

  handleUpdatePageContent = async (
    content,
    recordUndo = true,
    callbackFn = () => false,
    wait = 500
  ) => {
    // if (_.has(this.props, "onHandleUpdatePageContent"))
    //   this.props.onHandleUpdatePageContent(
    //     content,
    //     recordUndo,
    //     callbackFn,
    //     wait
    //   );

    this.debounce(() => {
      this.setState({ savingStatus: ["SAVING"] }, () => {
        this.setState(
          (prevContent) => {
            const { undoStack, undoPosition } = prevContent;

            if (!recordUndo) return {};
            return {
              undoStack: [
                ...undoStack.slice(0, undoPosition + 1),
                content.filter((itm) => itm.id !== CURSOR_ID),
              ],
              undoPosition: undoPosition + 1,
            };
          },
          () => {
            // filter out 'active' states
            const normalizedContent = _.map(content, (obj) => {
              if (_.get(obj, "state") === "active")
                return { ...obj, state: "normal" };
              else return obj;
            });

            const variables = {
              pageId: this.props.match.params.nodeId,
              content: normalizedContent,
            };

            this.props.updatePageContent({ variables }).then((response) => {
              this.setState({ savingStatus: ["SAVED", new Date()] });
              if (!wait) this.setState({ content }); // if wait flag is false, repeat the content
              callbackFn();
            });
          }
        );
      });
    }, wait);
  };

  renderFromState() {
    this.setState(this.pendingUpdateFn[0], this.pendingUpdateFn[1]);

    this.pendingUpdateFn = null;
    this.requestedFrame = null;
  }

  setCanDrag(canDrag, callbackFn = () => false) {
    // if (_.has(this.props, "onSetCanDrag"))
    //   this.props.onSetCanDrag(canDrag, callbackFn);

    this.setState({ canDrag }, callbackFn);
  }

  getCanDrag() {
    // if (_.has(this.props, "onGetCanDrag")) this.props.onGetCanDrag();
    return this.state.canDrag;
  }

  render() {
    const { app } = this.context;
    const { show, getPageQuery, match } = this.props;
    const { mobileState, content, showPublish } = this.state;
    const { campaignId, nodeId } = match.params;

    if (getPageQuery.loading) {
      return (
        <div style={{ textAlign: "center" }}>
          <img src={app.loadingImage} alt="Loading..." />
        </div>
      );
    }
    if (getPageQuery.error) {
      console.log(getPageQuery.error);
      return (
        <div style={{ textAlign: "center" }}>
          <img src={app.errorImage} alt="Connection Error" />
        </div>
      );
    }

    if (!content.length) return <div>...</div>;

    const mLeft = show !== "publish" ? 85 : 0; // 300

    const mainContainerStyle = {
      borderRadius: 3,
      height: "100%",
      backgroundColor: "white",
      boxShadow: "5px 5px 25px 0 rgba(46,61,73,.2)",
      width: show === "templates" ? "90%" : 1000,
      margin: "120px auto",
      ...mobileState.dimensions,
      maxWidth:
        show === "templates"
          ? "90%"
          : mobileState.dimensions.maxWidth || "unset",
    };

    const editorProps = {
      hidden: false,
      content: "edit",
      pageContent: content.length ? content : getPageQuery.page.content,
      removeItem: this.removeItem,
      duplicateItem: this.duplicateItem,
      moveThisByThat: this.moveThisByThat,
      addHoverCursor: this.addHoverCursor,
      addThisAfterThat: this.addThisAfterThat,
      changeState: this.changeState,
      state: this.state.state,
      updateContent: this.updateContent,
      updateComponentStyle: this.updateComponentStyle,
      updateComponentSettings: this.updateComponentSettings,
      listAncestors: this.listAncestors,
      listComponents: this.listComponents,
      setActiveObject: this.setActiveObject,
      doUndoRedo: this.doUndoRedo,
      undoStackSize: this.state.undoStack.length - 1,
      undoPosition: this.state.undoPosition,
      setMobileState: this.setMobileState,
      getMobileState: this.getMobileState,
      setActivePropertyWindows: this.setActivePropertyWindows,
      getActivePropertyWindows: this.getActivePropertyWindows,
      setCanDrag: this.setCanDrag,
      getCanDrag: this.getCanDrag,
    };

    if (show === "preview") {
      return <Builder {...this.props} {...editorProps} show="preview" />;
    }

    return (
      <div
        style={{
          marginLeft: mLeft,
          minHeight: "100vh",
          backgroundColor: "#F0F0F0",
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
        }}
      >
        <div
          style={{ ...style.bigToolbar.main, marginLeft: mLeft, zIndex: 301 }}
        >
          {showPublish ? (
            <PublishSuccessPopup
              {...this.props}
              onClose={() => this.setState({ showPublish: false })}
            />
          ) : null}
          <AppDrawer
            hidden={!this.state.appDrawerVisible}
            toggleAppDrawer={this.toggleAppDrawer}
          />
          <Toolbar
            leftActionsGroup={leftActionsGroup}
            title={() => (
              <RenamableTitle
                {...this.props}
                name={this.props.getPageQuery.page.name}
                onChange={(pageName) => {
                  this.props
                    .updatePageName({
                      variables: {
                        pageId: this.props.getPageQuery.page.id,
                        name: pageName,
                      },
                    })
                    .then((result) => {
                      const object = result.data.updatePage.object;
                      console.log({ object });
                      console.log("PAGE IS RENAMED", result);
                      if (object) {
                        this.props
                          .updateCampaignObjectMutation({
                            variables: {
                              name: pageName,
                              deleted: false,
                              screenshot: object.screenshot,
                              id: object.id,
                              connectToIds: object
                                ? object.connectTo.map((obj) => ({
                                    id: obj.id,
                                  }))
                                : [],
                            },
                          })
                          .then((json) => {
                            // console.log({ nodeId });
                            this.props.getPageQuery.refetch({
                              variables: { pageId: nodeId },
                            });
                            this.props.getCampaignQuery.refetch({
                              variables: { campaignId },
                            });
                          });
                      }
                    });
                }}
              />
            )}
            pages={_.filter(
              _.get(this.props, "getCampaignQuery.campaign.objects", []),
              (itmm) => itmm.type === "PageComponent"
            )}
            match={this.props.match}
            rightActionsGroup={rightActionsGroup}
            toggleAppDrawer={this.toggleAppDrawer}
            theme="light"
            doUndoRedo={this.doUndoRedo}
            undoPosition={this.state.undoPosition}
            undoStackSize={this.state.undoStack.length - 1}
            onPublish={() => this.setState({ showPublish: true })}
            savingStatus={this.state.savingStatus}
          />
        </div>
        <div
          style={{
            width: mLeft,
            backgroundColor: theme.darkColor,
            position: "fixed",
            top: 0,
            left: 0,
            bottom: 0,
            zIndex: 200,
          }}
        >
          <TabSidebar
            {...this.props}
            content={content}
            listComponents={this.listComponents}
            mobileState={mobileState}
          />
        </div>
        <div style={mainContainerStyle}>
          <div style={{ height: "100%" }}>
            {show === "seo" && (
              <div style={{ padding: 35 }}>
                <h2 style={{ textAlign: "center" }}>
                  What should the search results show when someone
                  <br />
                  uses a search engine to find your page?
                </h2>
                <SEO {...this.props} />
              </div>
            )}
            {show === "email" && (
              <div style={{ padding: 35 }}>
                <EmailSettings
                  {...this.props}
                  hidden={false}
                  step={match.params.step}
                  showProvider={app.showProviderStep}
                />
              </div>
            )}
            {show === "merchant" && (
              <MerchantSettings
                {...this.props}
                hidden={false}
                step={match.params.step}
                showProvider={app.showProviderStep}
              />
            )}
            {show === "tracking" && (
              <div style={{ padding: 35 }}>
                <Tracking {...this.props} />
              </div>
            )}
            {show === "css" && (
              <div style={{ padding: 35 }}>
                <CSS {...this.props} />
              </div>
            )}
            {show === "exit" && (
              <div style={{ padding: 35, height: "100%" }}>
                <ExitIntent {...this.props} {...editorProps} />
              </div>
            )}
            {show === "history" && (
              <div style={{ padding: 35, height: "100%" }}>
                <History {...this.props} {...editorProps} />
              </div>
            )}
            {show === "templates" && (
              <Templates
                {...this.props}
                {...editorProps}
                tab={match.params.type}
                title={false}
              />
            )}
            {show === "builder" && <Builder {...this.props} {...editorProps} />}
          </div>
        </div>
      </div>
    );
  }
}

export default Canvas;
