class LevelsUI extends FormApplication {
  constructor() {
    super();
    this.range = [];
    this.rangeEnabled = false;
    this.isEdit = false;
    this.definedLevels = [];
    this.roofEnabled = false;
    this.placeOverhead = false;
    this.stairEnabled = true;
  }

  static get defaultOptions() {
    return {
      ...super.defaultOptions,
      title: game.i18n.localize("levels.ui.title"),
      id: "levelsUI",
      template: `modules/levels/templates/layerTool.hbs`,
      resizable: true,
      dragDrop: [{ dragSelector: null, dropSelector: null }],
    };
  }

  get currentRange() {
    const bgElev = canvas.primary.background.elevation;
    if(!this.rangeEnabled) return { bottom: bgElev, top: bgElev };
    if(!this.range?.length) return { bottom: bgElev, top: bgElev };
    return {
      bottom: parseFloat(this.range[0]),
      top: parseFloat(this.range[1]),
    }
  }

  getData() {
    return {};
  }

  async activateListeners(html) {
    ui.controls.control.foreground = true;
    canvas.tiles._activateSubLayer(true);
    this.rangeEnabled = true;
    this.loadLevels();
    html.on("click", ".level-item", this._onChangeLevel.bind(this));
    html.on("click", ".level-item .fa-trash", this._onRemoveLevel.bind(this));
    html.on(
      "click",
      "#levels-ui-controls .fa-trash",
      this._onClearLevels.bind(this)
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-plus",
      this._onAddLevel.bind(this)
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-edit",
      this._onToggleEdit.bind(this)
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-map",
      this._onGetFromScene.bind(this)
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-users",
      this._onShowPlayerList.bind(this)
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-archway",
      () => {
        this.roofEnabled = !this.roofEnabled;
        this.setButtonStyles();
        this.computeLevelsVisibility();
      }
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-tree",
      () => {
        this.placeOverhead = !this.placeOverhead;
        this.setButtonStyles();
      }
    );
    html.on(
      "click",
      "#levels-ui-controls .fa-sort-amount-up-alt",
      () => {
        this.stairEnabled = !this.stairEnabled;
        this.setButtonStyles();
      }
    );

    html.on("click", ".player-portrait", this._onControlToken.bind(this));
    html.on("change", ".level-inputs input", this.saveData.bind(this));
    //make list sortable
    html.find("#levels-list").sortable({
      axis: "y",
      handle: ".fa-arrows-alt",
      update: this.saveData.bind(this),
    });
    const index = this.definedLevels
      ? this.definedLevels.indexOf(
          this.definedLevels.find(
            (l) =>
              l[0] == this.range[0] &&
              l[1] == this.range[1] &&
              l[2] == this.range[2]
          )
        )
      : undefined;
    if (index === undefined || index === -1) {
      html.find("#levels-list li:last-child").click();
    } else html.find("#levels-list li")[index].click();
    this.updatePlayerList();
    this.setButtonStyles();
  }

  setButtonStyles() {
    this.element.find(".fa-archway").toggleClass("active", this.roofEnabled);
    this.element.find(".fa-tree").toggleClass("active", this.placeOverhead);
    this.element.find(".fa-sort-amount-up-alt").toggleClass("active", this.stairEnabled);
    this.element.find(".fa-users").toggleClass("active", this.element.find(".players-on-level").hasClass("active"));
  }

  _onAddLevel(event) {
    let $li = this.generateLi([0, 0, ""]);
    $("#levels-list").append($li);
  }
  //toggle readonly property of inputs and toggle visibility of trash icon
  _onToggleEdit(event) {
    this.isEdit = !this.isEdit;
    let $inputs = $(".level-inputs input");
    $inputs.prop("readonly", !$inputs.prop("readonly"));
    $(".level-item .fa-trash").toggleClass("hidden");
    $(".level-item .fa-arrows-alt").toggleClass("hidden");
    this.saveData();
  }

  activateForeground(){
    try{
      ui.controls.control.foreground = true;
      ui.controls.control.foreground = true;
      canvas.tiles._activateSubLayer(true);
      canvas.perception.update({refreshLighting: true, refreshTiles: true}, true);
      const fgControl = document.querySelector(`[data-tool="foreground"]`)
      if(fgControl) fgControl.classList.add("active")
    }catch(e){}
  }

  _onChangeLevel(event) {
    this.activateForeground()
    if (!$(event.target).hasClass("player-portrait"))
      canvas.tokens.releaseAll();
    let $target = $(event.currentTarget);
    let $parent = $target.parent();
    $parent.find(".fa-caret-right").removeClass("active");
    $parent.find("li").removeClass("active");
    $target.find(".fa-caret-right").addClass("active");
    $target.addClass("active");
    const top = $target.find(".level-top").val();
    const bottom = $target.find(".level-bottom").val();
    const name = $target.find(".level-name").val();
    this.definedLevels = canvas.scene.getFlag(
      CONFIG.Levels.MODULE_ID,
      "sceneLevels"
    );
    this.range = this.definedLevels?.find((l) => l[0] == bottom && l[1] == top) ?? [parseFloat(bottom), parseFloat(top)];
    if ($(event.target).hasClass("player-portrait")) return;
    WallHeight.currentTokenElevation = parseFloat(bottom);
    this.computeLevelsVisibility(this.range);
    Hooks.callAll("levelsUiChangeLevel");
  }

  _onRemoveLevel(event) {
    Dialog.confirm({
      title: game.i18n.localize("levels.dialog.removeLevel.title"),
      content: game.i18n.localize("levels.dialog.removeLevel.content"),
      yes: () => {
        let $target = $(event.currentTarget);
        $target.remove();
        this.saveData();
      },
      no: () => {},
      defaultYes: false,
    });
  }

  _onGetFromScene(event) {
    Dialog.confirm({
      title: game.i18n.localize("levels.dialog.getFromScene.title"),
      content: game.i18n.localize("levels.dialog.getFromScene.content"),
      yes: (html) => {
        const maxRange = parseFloat(html.find("#maxelevationdifference").val());
        this.getFromScene(maxRange);
      },
      no: () => {},
      render: (html) => {
        const maxRange = `
        <hr>
        <div class="form-group" style="display: grid;grid-template-columns: 1fr 1fr;align-items: center;">
          <label>${game.i18n.localize("levels.ui.minElevDiff")}</label>
          <input type="text" id="maxelevationdifference" data-dtype="Number" value="9" placeholder="">
        </div>
        <br>
        `
        $(html[0]).append(maxRange);
      },
      defaultYes: false,
    });
  }

  _onShowPlayerList(event) {
    this.element.find(".players-on-level").toggleClass("active");
    this.setButtonStyles();
  }

  _onControlToken(event) {
    canvas.tokens.releaseAll();
    const tokenId = event.currentTarget.dataset.tokenid;
    const token = canvas.tokens.get(tokenId);
    token.control();
  }

  saveData() {
    let data = [];
    $(this.element)
      .find("li")
      .each((index, element) => {
        let $element = $(element);
        let name = $element.find(".level-name").val();
        let top = $element.find(".level-top").val();
        let bottom = $element.find(".level-bottom").val();
        data.push([bottom, top, name]);
      });
    canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", data);
  }

  async loadLevels() {
    $("#levels-list").empty();
    let levelsFlag =
      canvas.scene.getFlag(CONFIG.Levels.MODULE_ID, "sceneLevels") || [];
    this.definedLevels = levelsFlag;
    this.range = this.range ?? this.definedLevels[levelsFlag.length - 1];
    if (levelsFlag) {
      for (let level of levelsFlag) {
        this.element.find("#levels-list").append(this.generateLi(level));
      }
    }
  }

  generateLi(data) {
    //data 0 - top 1- bottom 2- name
    let $li = $(`
	<li class="level-item" draggable>
    <i class="fas fa-arrows-alt"></i>
    <div class="players-on-level"></div>
    <i class="fas fa-caret-right"></i>
    <div class="level-inputs">
    <input type="text" class="level-name" value="${
      data[2] ?? ""
    }" placeholder="${game.i18n.localize("levels.widget.element")}">
    <i class="fas fa-caret-down"></i>
    <input type="number" class="level-bottom" value="${
      data[0]
    }" placeholder="0">
    <i class="fas fa-caret-up"></i>
    <input type="number" class="level-top" value="${data[1]}" placeholder="0">
    <i class="fas fa-trash"></i>
    </div>
	</li>
	`);
    $li.find("input").prop("readonly", !this.isEdit);
    $li.find(".fa-trash").toggleClass("hidden", this.isEdit);
    $li.find(".fa-arrows-alt").toggleClass("hidden", this.isEdit);
    return $li;
  }

  async _onClearLevels() {
    Dialog.confirm({
      title: game.i18n.localize("levels.dialog.levelsclear.title"),
      content: game.i18n.localize("levels.dialog.levelsclear.content"),
      yes: async () => {
        await canvas.scene.setFlag(CONFIG.Levels.MODULE_ID, "sceneLevels", []);
        this.loadLevels();
      },
      no: () => {},
      defaultYes: false,
    });
  }

  updatePlayerList() {
    const playerActors = Array.from(game.users).map(
      (user) => user.character?.id
    );
    const players = canvas.tokens.placeables.filter((token) =>
      playerActors.includes(token.actor?.id)
    );
    $(this.element)
      .find("li")
      .each((index, element) => {
        let $element = $(element);
        const top = $element.find(".level-top").val();
        const bottom = $element.find(".level-bottom").val();
        const $playerList = $element.find(".players-on-level");
        $playerList.empty();
        players.forEach((player) => {
          if (
            player.losHeight >= bottom &&
            player.losHeight < top &&
            player.id
          ) {
            const color = Array.from(game.users).find(
              (user) => user.character?.id == player?.actor?.id
            )?.border;
            $playerList.append(
              `<img class="player-portrait" data-tokenid="${player.id}" title="${player.actor?.name}" style="border-color: ${color}" src="${player.document.texture.src}">`
            );
          }
        });
      });
    this.element.css("height", "auto");
  }

  close(force = false) {
    if (!force) this.saveData();
    this.rangeEnabled = false;
    if (!force) this.computeLevelsVisibility();
    CONFIG.Levels.handlers.RefreshHandler.restoreVisAll();
    CONFIG.Levels.handlers.RefreshHandler.refreshAll();
    WallHeight.schedulePerceptionUpdate()
    super.close();
  }

  async getFromScene(maxRange = 9) {
    let autoLevels = {};
    for (let wall of canvas.walls.placeables) {
      const { top, bottom } = WallHeight.getWallBounds(wall);
      let entityRange = [bottom, top];
      if (
        entityRange[0] != -Infinity &&
        entityRange[1] != Infinity &&
        (entityRange[0] || entityRange[0] == 0) &&
        (entityRange[1] || entityRange[1] == 0)
      ) {
        autoLevels[`${entityRange[0]}${entityRange[1]}`] = entityRange;
      }
    }

    for (let tile of canvas.tiles.placeables.filter(
      (t) => t.document.overhead
    )) {
      let { rangeBottom, rangeTop } =
        CONFIG.Levels.helpers.getRangeForDocument(tile);
      if (
        (rangeBottom || rangeBottom == 0) &&
        (rangeTop || rangeTop == 0) &&
        rangeTop != Infinity &&
        rangeBottom != -Infinity
      ) {
        autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
      }
    }

    for (let light of canvas.lighting.placeables) {
      let { rangeBottom, rangeTop } =
        CONFIG.Levels.helpers.getRangeForDocument(light);
      if (
        (rangeBottom || rangeBottom == 0) &&
        (rangeTop || rangeTop == 0) &&
        rangeTop != Infinity &&
        rangeBottom != -Infinity
      ) {
        autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
      }
    }

    for (let drawing of canvas.drawings.placeables) {
      let { rangeBottom, rangeTop } =
        CONFIG.Levels.helpers.getRangeForDocument(drawing);
      if (
        (rangeBottom || rangeBottom == 0) &&
        (rangeTop || rangeTop == 0) &&
        rangeTop != Infinity &&
        rangeBottom != -Infinity
      ) {
        autoLevels[`${rangeBottom}${rangeTop}`] = [rangeBottom, rangeTop];
      }
    }
    let autoRange = Object.entries(autoLevels)
      .map((x) => x[1])
      .filter( x => Math.abs(x[1] - x[0]) >= maxRange)
      .sort()
      .reverse();
    if (autoRange.length) {
      await canvas.scene.setFlag(
        CONFIG.Levels.MODULE_ID,
        "sceneLevels",
        autoRange
      );
      this.loadLevels();
    }
  }

  computeLevelsVisibility() {
    WallHeight.currentTokenElevation = parseFloat(this.range[0] ?? 0);
    CONFIG.Levels.handlers.RefreshHandler.refreshAll();
    WallHeight.schedulePerceptionUpdate();
  }

  computeRangeForDocument(document, range, isTile = false) {
    let { rangeBottom, rangeTop } =
      CONFIG.Levels.helpers.getRangeForDocument(document);
    rangeBottom = rangeBottom ?? -Infinity;
    rangeTop = rangeTop ?? Infinity;
    range[0] = parseFloat(range[0]) ?? -Infinity;
    range[1] = parseFloat(range[1]) ?? Infinity;
    let entityRange = [rangeBottom, rangeTop];
    if (!isTile) {
      if (
        (entityRange[0] >= range[0] && entityRange[0] <= range[1]) ||
        (entityRange[1] >= range[0] && entityRange[1] <= range[1])
      ) {
        return true;
      } else {
        return false;
      }
    } else {
      if (entityRange[0] == range[1] + 1 && entityRange[1] == Infinity) {
        return true;
      } else {
        if (entityRange[0] >= range[0] && entityRange[1] <= range[1]) {
          return true;
        } else {
          return false;
        }
      }
    }
  }

  getObjUpdateData(range) {
    return {
      flags: {
        [`${CONFIG.Levels.MODULE_ID}`]: {
          rangeBottom: parseFloat(range[0]),
          rangeTop: parseFloat(range[1]),
        },
      },
    };
  }

  async elevationDialog(tool) {
    let content = `
    <div class="form-group">
    <label for="elevation">${game.i18n.localize(
      "levels.template.elevation.name"
    )}</label>
    <div class="form-fields">
        <input type="number" name="templateElevation" data-dtype="Number" value="${
          canvas.tokens.controlled[0]?.document?.elevation ?? 0
        }" step="1">
    </div>
    </div>
    <p></p>
    <div class="form-group">
    <label for="special">${game.i18n.localize(
      "levels.template.special.name"
    )}</label>
    <div class="form-fields">
        <input type="number" name="special" data-dtype="Number" value="0" step="1">
    </div>
    </div>
    <p></p>
    `;
    let ignoreClose = false;
    let toolhtml = $("body").find(`li[data-tool="setTemplateElevation"]`);
    let dialog = new Dialog({
      title: game.i18n.localize("levels.dialog.elevation.title"),
      content: content,
      buttons: {
        confirm: {
          label: game.i18n.localize("levels.yesnodialog.yes"),
          callback: (html) => {
            CONFIG.Levels.UI.nextTemplateHeight = html.find(
              `input[name="templateElevation"]`
            )[0].valueAsNumber;
            CONFIG.Levels.UI.nextTemplateSpecial = html.find(
              `input[name="special"]`
            )[0].valueAsNumber;
            CONFIG.Levels.UI.templateElevation = true;
            ignoreClose = true;
            tool.active = true;
            if (toolhtml[0])
              $("body")
                .find(`li[data-tool="setTemplateElevation"]`)
                .addClass("active");
          },
        },
        close: {
          label: game.i18n.localize("levels.yesnodialog.no"),
          callback: () => {
            CONFIG.Levels.UI.nextTemplateHeight = undefined;
            CONFIG.Levels.UI.nextTemplateSpecial = undefined;
            CONFIG.Levels.UI.templateElevation = false;
            tool.active = false;
            if (toolhtml[0])
              $("body")
                .find(`li[data-tool="setTemplateElevation"]`)
                .removeClass("active");
          },
        },
      },
      default: "confirm",
      close: () => {
        if (ignoreClose == true) {
          ignoreClose = false;
          return;
        }
        CONFIG.Levels.nextTemplateHeight = undefined;
        CONFIG.Levels.nextTemplateSpecial = undefined;
        CONFIG.Levels.templateElevation = false;
        tool.active = false;
        if (toolhtml[0])
          $("body")
            .find(`li[data-tool="setTemplateElevation"]`)
            .removeClass("active");
      },
    });
    await dialog._render(true);
  }
}

$(document).on("click", `li[data-control="levels"]`, (e) => {
  CONFIG.Levels.UI.render(true);
})

Hooks.on("renderSceneControls", (controls, b, c) => {
  if(game.user.isGM){
    $(".main-controls").append(`
    <li class="scene-control " data-control="levels" data-tooltip="${game.i18n.localize("levels.controls.main.name")}">
    <i class="fas fa-layer-group"></i>
    </li>
    `)
  }
});

Hooks.on("ready", () => {
  if (game.user.isGM) {

    Hooks.on("activateTilesLayer", ()=>{
      if(CONFIG.Levels.UI.rangeEnabled){
        Hooks.once("renderSceneControls", ()=>{
          CONFIG.Levels.UI.activateForeground();
        })
      }
    })

    Hooks.on("canvasInit", () => {
      CONFIG.Levels.UI.close(true);
    })

    Hooks.on("updateToken", (token,updates)=>{
      if("elevation" in updates)CONFIG.Levels.UI.updatePlayerList();
    })

    Hooks.on("createToken", (token,updates)=>{
      CONFIG.Levels.UI.updatePlayerList();
    })

    Hooks.on("deleteToken", (token,updates)=>{
      CONFIG.Levels.UI.updatePlayerList();
    })

    Hooks.on("controlToken", (token,controlled)=>{
      if(CONFIG.Levels.UI.rangeEnabled && !canvas.tokens.controlled.length){
        CONFIG.Levels.UI.computeLevelsVisibility();
      }else if(CONFIG.Levels.UI.rangeEnabled){
        CONFIG.Levels.handlers.RefreshHandler.refresh(canvas.tokens);
      }
    })

    Hooks.on("renderLevelsUI", (app, html) => {

      if(!app.positionSet){
        console.log((window.innerWidth - $("#sidebar").width() - $("#levelsUI").width()))
        app.setPosition({
          top: 2,
          left: (window.innerWidth - $("#sidebar").width() - $("#levelsUI").width()) - 10,
          width: $("#levelsUI").width(),
          height: Math.max(150, $("#levelsUI").height()),
        });
        app.positionSet = true
      }
    })

    Hooks.on("preCreateTile", (tile, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true) {
        tile.updateSource({
          overhead: true,
        });
        if(!game.Levels3DPreview?._active){
          tile.updateSource({
            flags: {
              "betterroofs": {
                brMode: CONFIG.Levels.UI.roofEnabled,
              },
              [`${CONFIG.Levels.MODULE_ID}`]: {
                rangeBottom: CONFIG.Levels.UI.roofEnabled
                  ? parseFloat(CONFIG.Levels.UI.range[1])
                  : parseFloat(CONFIG.Levels.UI.range[0]),
                rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : parseFloat(CONFIG.Levels.UI.range[1]),
                allWallBlockSight: CONFIG.Levels.UI.roofEnabled
              }
            },
            roof: CONFIG.Levels.UI.roofEnabled,
          });
        }else{
          tile.updateSource({
            flags: {
              [`${CONFIG.Levels.MODULE_ID}`]: {
                rangeTop: CONFIG.Levels.UI.roofEnabled ? Infinity : CONFIG.Levels.UI.range[1],
              }
            }
          });
        }
        if(CONFIG.Levels.UI.placeOverhead){

          tile.updateSource({
            roof: false,
            flags: {
              [`${CONFIG.Levels.MODULE_ID}`]: {
                showIfAbove: true,
                noCollision: true,
                showAboveRange: parseFloat(CONFIG.Levels.UI.range[1]) - parseFloat(CONFIG.Levels.UI.range[0]),
                rangeBottom: parseFloat(CONFIG.Levels.UI.range[1]),
                rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
              }
            }
          });
        }
      }
    });

    Hooks.on("preCreateAmbientLight", (light, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true && !game.Levels3DPreview?._active) {
        light.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
      }
    });

    Hooks.on("preCreateAmbientSound", (sound, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true) {
        sound.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
      }
    });

    Hooks.on("preCreateNote", (note, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true) {
        note.updateSource(CONFIG.Levels.UI.getObjUpdateData(CONFIG.Levels.UI.range));
      }
    });

    Hooks.on("preCreateDrawing", (drawing, updates) => {
      let sortedLevels = [...CONFIG.Levels.UI.definedLevels].sort((a, b) => {
        return parseFloat(b[0]) - parseFloat(a[0])
      })
      let aboverange = sortedLevels.find(l => CONFIG.Levels.UI.range[0] === l[0] && CONFIG.Levels.UI.range[1] === l[1])
      aboverange = sortedLevels.indexOf(aboverange) === 0 ? undefined : sortedLevels[sortedLevels.indexOf(aboverange) - 1]

      if (aboverange) {
        let newTop = aboverange[1];
        let newBot = aboverange[0];
        if (CONFIG.Levels.UI.rangeEnabled == true) {
          drawing.updateSource({
            hidden: CONFIG.Levels.UI.stairEnabled,
            text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${newBot}` : "",
            flags: {
              levels: {
                drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
                rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
                rangeTop: newBot - 1,
              },
            },
          });
        }
      } else {
        if (CONFIG.Levels.UI.rangeEnabled == true) {
          drawing.updateSource({
            hidden: CONFIG.Levels.UI.stairEnabled,
            text: CONFIG.Levels.UI.stairEnabled ? `Levels Stair ${CONFIG.Levels.UI.range[0]}-${CONFIG.Levels.UI.range[1] + 1}` : "",
            flags: {
              levels: {
                drawingMode: CONFIG.Levels.UI.stairEnabled ? 2 : 0,
                rangeBottom: parseFloat(CONFIG.Levels.UI.range[0]),
                rangeTop: parseFloat(CONFIG.Levels.UI.range[1]),
              },
            },
          });
        }
      }
    });

    Hooks.on("preCreateWall", (wall, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true) {
        wall.updateSource({
          flags: {
            "wall-height": {
              bottom: parseFloat(CONFIG.Levels.UI.range[0]),
              top: parseFloat(CONFIG.Levels.UI.range[1]),
            },
          },
        });
      }
    });

    Hooks.on("preCreateToken", (token, updates) => {
      if (CONFIG.Levels.UI.rangeEnabled == true) {
        if(updates) updates.elevation = parseFloat(CONFIG.Levels.UI.range[0]);
        token.updateSource({
          elevation: updates?.elevation ?? parseFloat(CONFIG.Levels.UI.range[0]),
        });
      }
    });
  }
});

Hooks.on("getSceneControlButtons", (controls, b, c) => {
  let templateTool = {
    name: "setTemplateElevation",
    title: game.i18n.localize("levels.controls.setTemplateElevation.name"),
    icon: "fas fa-sort",
    toggle: true,
    active: CONFIG.Levels?.UI.templateElevation || false,
    onClick: (toggle) => {
      CONFIG.Levels.UI.templateElevation = toggle;
      if (toggle) CONFIG.Levels.UI.elevationDialog(templateTool);
      else CONFIG.Levels.UI.nextTemplateHeight = undefined;
    },
  };
  CONFIG.Levels.UI._levelsTemplateTool = templateTool;
  controls.find((c) => c.name == "token").tools.push(templateTool);
});

Hooks.once("canvasReady", () => {
  console.log(
    `%cLEVELS\n%cWelcome to the 3rd Dimension`,
    "font-weight: bold;text-shadow: 10px 10px 0px rgba(0,0,0,0.8), 20px 20px 0px rgba(0,0,0,0.6), 30px 30px 0px rgba(0,0,0,0.4);font-size:100px;background: #444; color: #d43f3f; padding: 2px 28px 0 2px; display: inline-block;",
    "font-weight: bold;text-shadow: 2px 2px 0px rgba(0,0,0,0.8), 4px 4px 0px rgba(0,0,0,0.6), 6px 6px 0px rgba(0,0,0,0.4);font-size:20px;background: #444; color: #d43f3f; padding: 10px 27px; display: inline-block; margin-left: -30px"
  );
});