// Vue App
const app = new Vue({
  el: '#app',

  components: {
    'model': ModelComponent,
    'material': MaterialComponent,
    'door': DoorComponent,
    'handle': HandleComponent,
    'component-page': ComponentPage
  },

  data: {
    // Global links from common.js
    HOMEPAGE: "",
    HOMEPAGE_EN: HOMEPAGE_EN,
    HOMEPAGE_VI: HOMEPAGE_VI,
    FACEBOOK: FACEBOOK,
    STORE: STORE,
    NOTICE_EN: NOTICE_EN,
    NOTICE_VI: NOTICE_VI,

    modelUnits: "metric",
    currentTheme: 'light',
    themeIcon: 'sun',
    language: 'zh-CN',
    languageData: {},

    noticeType: "info",
    noticeMessage: "",
    modalTitle: "",
    editTitle: "",
    editAction: null,
    modalMessage: "",
    modalAction0: null,
    modalAction1: null,
    modalAction2: null,

    currentTab: 'model',
    searchQuery: '',
    thumbnailsFolderPath: 'My Documents',
    settingsFolderPath: '',

    explorerName: 'explorer', // or 'finder',
    requireOpenFolderPath: '',
    isProcessing: false, // Track if processing modal is showing
  },

  mounted() {
    // 供 Ruby 回调：返回某路径下的子文件夹列表后触发，中间列树形展开用
    window.dispatchSubfolderChildrenLoaded = function(path, children) {
      window.dispatchEvent(new CustomEvent('subfolder-children-loaded', { detail: { path: path, children: children || [] } }));
    };

    // 语言由 Ruby ready 回调通过 applyPluginLanguage 注入（与全局配置一致）

    // Theme
    const savedTheme = localStorage.getItem(themeKey) || "light";
    this.themeIcon = savedTheme === "light" ? "moon" : "sun";
    this.currentTheme = savedTheme;
    applyTheme(savedTheme);

    // Restore active tab
    const activeTabId = localStorage.getItem(activeTabKey) || 'firstTab';
    if (activeTabId === 'secondTab') {
      this.currentTab = 'material';
    } else if (activeTabId === 'thirdTab') {
      this.currentTab = 'door';
    } else if (activeTabId === 'fourthTab') {
      this.currentTab = 'handle';
    } else if (activeTabId === 'fifthTab') {
      this.currentTab = 'component';
    } else {
      this.currentTab = 'model';
    }

    // Initial ready call
    if (this.currentTab === 'model') {
      sketchup.ready('model');
    } else if (this.currentTab === 'material') {
      sketchup.ready('material');
    } else if (this.currentTab === 'door') {
      sketchup.ready('door');
    } else if (this.currentTab === 'handle') {
      sketchup.ready('handle');
    } else if (this.currentTab === 'component') {
      sketchup.ready('component');
    }

    // Activate Bootstrap tab after Vue renders
    this.$nextTick(() => {
      const tabElement = document.getElementById(activeTabId);
      if (tabElement) {
        $(tabElement).tab('show');
      }

      // Handle tool tip by Bootstrap
      handleTooltip(this);
    });

  },

  watch: {
  },

  methods: {
    applyPluginLanguage(lang) {
      if (!lang || lang === this.language) {
        if (lang && Object.keys(this.languageData).length === 0) {
          loadLanguage(this);
        }
        return;
      }
      this.language = lang;
      loadLanguage(this);
      handleTooltip(this);
    },

    translated(key) {
      return this.languageData[key] || key;
    },

    switchTheme() {
      const newTheme = this.currentTheme === 'light' ? 'dark' : 'light';

      applyTheme(newTheme);
      sketchup.switchTheme();
      this.currentTheme = newTheme;
      this.themeIcon = this.currentTheme === 'light' ? 'moon' : 'sun';
      localStorage.setItem(themeKey, newTheme);
    },

    updateUnitSystem(unitSystem) {
      this.modelUnits = unitSystem;
    },

    updateUrls(urls) {
      this.HOMEPAGE_EN      = urls.homepageEn || HOMEPAGE_EN;
      this.HOMEPAGE_VI      = urls.homepageVi || HOMEPAGE_VI;
      this.STORE            = urls.store || STORE;
      this.NOTICE_EN        = urls.noticeEn || NOTICE_EN;
      this.NOTICE_VI        = urls.noticeVi || NOTICE_VI;
    },

    handleToggleSidebar() {
      if (this.currentTab === 'model' && this.$refs.modelComponent) {
        this.$refs.modelComponent.toggleSubfolderColumn('model-app');
      } else if (this.currentTab === 'material' && this.$refs.materialComponent) {
        this.$refs.materialComponent.toggleSubfolderColumn('material-app');
      } else if (this.currentTab === 'door' && this.$refs.doorComponent) {
        this.$refs.doorComponent.toggleSubfolderColumn('door-app');
      } else if (this.currentTab === 'handle' && this.$refs.handleComponent) {
        this.$refs.handleComponent.toggleSubfolderColumn('handle-app');
      } else if (this.currentTab === 'component' && this.$refs.componentComponent) {
        this.$refs.componentComponent.toggleSubfolderColumn('component-app');
      }
    },

    onHeaderSearchEnter() {
      const ref =
        this.currentTab === 'model' ? this.$refs.modelComponent :
        this.currentTab === 'material' ? this.$refs.materialComponent :
        this.currentTab === 'door' ? this.$refs.doorComponent :
        this.currentTab === 'handle' ? this.$refs.handleComponent :
        this.$refs.componentComponent;
      if (ref && typeof ref.handleDeepSearch === 'function') ref.handleDeepSearch();
    },

    toggleActiveDeepSearch() {
      const ref =
        this.currentTab === 'model' ? this.$refs.modelComponent :
        this.currentTab === 'material' ? this.$refs.materialComponent :
        this.currentTab === 'door' ? this.$refs.doorComponent :
        this.currentTab === 'handle' ? this.$refs.handleComponent :
        this.$refs.componentComponent;
      if (ref && typeof ref.toggleDeepSearch === 'function') ref.toggleDeepSearch();
    },

    toggleTab(newTab) {
      this.currentTab = newTab;

      if (newTab === 'model') {
        sketchup.ready('model');
        updateDynamicWidth('model-app');
        localStorage.setItem(activeTabKey, 'firstTab');
      } else if (newTab === 'material') {
        sketchup.ready('material');
        updateDynamicWidth('material-app');
        localStorage.setItem(activeTabKey, 'secondTab');
      } else if (newTab === 'door') {
        sketchup.ready('door');
        updateDynamicWidth('door-app');
        localStorage.setItem(activeTabKey, 'thirdTab');
      } else if (newTab === 'handle') {
        sketchup.ready('handle');
        updateDynamicWidth('handle-app');
        localStorage.setItem(activeTabKey, 'fourthTab');
      } else if (newTab === 'component') {
        sketchup.ready('component');
        updateDynamicWidth('component-app');
        localStorage.setItem(activeTabKey, 'fifthTab');
      }
    },

    // Settings methods
    handleThemeToggle() {
      applyTheme();
    },

    updateSettingsFolderPath(path) {
      this.settingsFolderPath = path;
      handleTooltip(this);
    },

    importSettings() {
      const message = this.translated("importSettingsMessage");
      const action = () => sketchup.importSettings();

      this.showNoticeModal(message, 'cancel', action);
    },

    thumbnailsFolderSelect() {
      sketchup.thumbnailsFolder();
    },

    updateThumbnailsFolderPath(path, notice) {
      this.thumbnailsFolderPath = path;

      if (!notice) return;

      const noticeMessage = this.translated('updateThumbnailsFolderMessage') + "<br>" + "<b>" + path + "</b>";
      this.showNoticeModal(noticeMessage, null, actionModal);
    },

    updateExplorerName(name) {
      this.explorerName = name;
    },

    updateRequireOpenFolderPath(path) {
      this.requireOpenFolderPath = path;
    },

    openFolder() {
      sketchup.openFolder(this.requireOpenFolderPath);
    },

    // ===== MODAL METHODS =====
    // This is also for receive message from SketchUp
    showMessageModal(message, type, delay = 1500, restoreModal = false) {
      if (!message) return;

      this.noticeMessage = message;
      this.noticeType = type || "info";

      // Track processing state for 'updating' type with 'wait' delay
      if (type === 'updating' && delay === 'wait') {
        this.isProcessing = true;
      }

      this.showToast(delay);
    },

    // Cancel/hide processing modal immediately
    cancelProcessingModal() {
      if (this.isProcessing) {
        this.isProcessing = false;
        forceHideAllModals();
      }
    },

    // Cancel deep search and hide modal
    cancelDeepSearch() {
      if (this.currentTab === 'model') {
        sketchup.cancelDeepSearchModel();
        if (this.$refs.modelComponent) this.$refs.modelComponent.clearDeepSearch();
      } else if (this.currentTab === 'material') {
        sketchup.cancelDeepSearchMaterial();
        if (this.$refs.materialComponent) this.$refs.materialComponent.clearDeepSearch();
      } else if (this.currentTab === 'door') {
        if (typeof sketchup.cancelDeepSearchDoor === 'function') sketchup.cancelDeepSearchDoor();
        if (this.$refs.doorComponent) this.$refs.doorComponent.clearDeepSearch();
      } else if (this.currentTab === 'handle') {
        if (typeof sketchup.cancelDeepSearchHandle === 'function') sketchup.cancelDeepSearchHandle();
        if (this.$refs.handleComponent) this.$refs.handleComponent.clearDeepSearch();
      }
      forceHideAllModals();
    },

    // This is also for receive notice from SketchUp
    showNoticeModal(message, action1 = null, action2 = null) {
      if (!message) return;

      this.modalTitle = "notification";
      this.modalMessage = message;

      // Configure action1 based on type
      if (action1) {
        if (action1 === "openFolder" || action1 === "openFile") {
          this.modalAction1 = {
            text: this.translated(action1),
            action: () => {
              this.openFolder();
            },
          };
        } else if (typeof action1 === 'function') {
          this.modalAction1 = {
            text: this.translated('cancel'),
            action: action1,
          };
        } else {
          this.modalAction1 = {
            text: this.translated('cancel'),
            action: () => null,
          };
        }
      } else {
        this.modalAction1 = null; // Clear modalAction1 if no action1 provided
      }

      // Configure action2 based on type
      if (action2) {
        this.modalAction2 = {
          text: 'OK',
          action: () => {
            if (action2) {
              action2();
            }
          },
        };
      } else {
        this.modalAction2 = {
          text: 'OK',
          action: () => {
            if (action2) {
              action2();
            }
          },
        };
      }

      // Force hide all modals (including processing modal) before showing notice
      // This prevents timing conflicts when SketchUp returns faster than modal animation
      forceHideAllModals();

      // Small delay to ensure DOM is clean before showing new modal
      setTimeout(() => {
        this.showModal("#actionModal", "wait");
      }, 50);
    },

    showAbcModal() {
      this.modalTitle = 'confirm';
      this.modalMessage = 'requireSafeCloseDialog';
      this.modalAction0 = { text: 'saveAndClose', action: () => null };
      this.modalAction1 = { text: 'cancel', action: () => this.hideModal('#actionModal') };
      this.modalAction2 = { text: 'OK', action: () => this.closeDialog() };

      this.showModal('#actionModal', 'wait');
    },

    showModal(id, delay = 1500) {
      showModal(id, delay);
    },

    hideModal(id) {
      hideModal(id);
    },

    hideAllModals() {
      hideAllModals();
    },

    showToast(delay = 1500) {
      showToast(delay);
    },
  },
});

// Global functions for SketchUp to call to update data

function updateExplorerName(data) {
  document.getElementById("app").__vue__.updateExplorerName(data);
};

function updateUnitSystem(data) {
  document.getElementById("app").__vue__.updateUnitSystem(data);
};

function updateUrls(urls) {
  document.getElementById("app").__vue__.updateUrls(urls);
}

function noticeNewVersion(/* data */) {
  /* 已移除：设置内检查更新/新版本提示相关功能 */
}

function showNoticeModal(notice, action1 = null, action2 = null) {
  document.getElementById("app").__vue__.showNoticeModal(notice, action1, action2);
}

function showMessageModal(message, type, delay = null, restoreModal = false) {
  document.getElementById("app").__vue__.showMessageModal(message, type, delay, restoreModal);
}

function updateThumbnailsFolderPath(path, notice) {
  document.getElementById("app").__vue__.updateThumbnailsFolderPath(path, notice);
}

function updateRequireOpenFolderPath(path) {
  document.getElementById("app").__vue__.updateRequireOpenFolderPath(path);
}

function updateCustomThumbnail(value) {
  document.getElementById("app").__vue__.updateCustomThumbnail(value);
}

function updateExtensionImagesPath(value) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateExtensionImagesPath(value);
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateExtensionImagesPath(value);
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateExtensionImagesPath(value);
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateExtensionImagesPath(value);
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateExtensionImagesPath(value);
};

function updateSettingsFolderPath(path) {
  document.getElementById('app').__vue__.updateSettingsFolderPath(path);
};

async function checkDomainExists(url) {
  try {
    const response = await fetch(url, { method: 'HEAD', mode: 'cors' });
    if (!response.ok) throw new Error('Domain does not exist or is unreachable.');
    if (response.redirected) return false;
    return true;
  } catch (error) {
    console.error('Error checking domain existence:', error.message);
    return false;
  }
}

async function canEmbedInIframe(url) {
  const domainExists = await checkDomainExists(url);
  if (!domainExists) return false;

  try {
    const response = await fetch(url, { method: 'HEAD', mode: 'cors' });
    const xFrameOptions = response.headers.get('X-Frame-Options');
    if (xFrameOptions && (xFrameOptions === 'DENY' || xFrameOptions === 'SAMEORIGIN')) return false;

    const csp = response.headers.get('Content-Security-Policy');
    if (csp && csp.includes('frame-ancestors')) return false;

    return true;
  } catch (error) {
    return false;
  }
}

function updateDynamicWidth(value) {
  // Wait for DOM to render
  requestAnimationFrame(() => {
    const container = document.getElementById(value);
    if (!container) return;

    const sidebar = container.classList.contains('sidebar-open');

    if (sidebar) {
      document.documentElement.style.setProperty('--dynamic-width', `370px`);
    } else {
      document.documentElement.style.setProperty('--dynamic-width', `165px`);
    }
  });
}

// Model Global Functions
window.updateModelFolders = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateFolders(data);
}
window.updateActiveModelFolder = function(folderPath) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateActiveFolder(folderPath);
}
window.updateRecentModelFolder = function(folderPath) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateRecentFolder(folderPath);
}
window.updateModelTotalInModel = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateTotalInModel(data);
}
window.updateModelFavorites = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateFavorites(data);
}
window.updateModelRecent = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateRecent(data);
}
window.updateModelRecentChildFolder = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateRecentChildFolder(data);
}
window.updateModelOnlineSources = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateOnlineSources(data);
}
window.updateModelItems = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateItems(data);
}
window.addNewModelItem = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.addNewItem(data);
}
window.updateRenamedModelItem = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateRenamedItem(data);
}
window.forceRefreshModelThumbnails = function() {
  if (app.$refs.modelComponent) app.$refs.modelComponent.forceRefreshThumbnails();
}
window.updateActiveModel = function(isActive, path) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateActive(isActive, path);
}
window.updateSelectedModels = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateSelected(data);
}
window.updateDeleteModelItems = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateDeleteItems(data);
}
window.updateIsDriveModel = function(isDrive) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateIsDrive(isDrive);
}
window.updateModelShowAll = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateShowAll(data);
}
window.updateDeepSearchModels = function(data) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.updateDeepSearchResults(data);
}
window.setDeepSearchLoadingModels = function(isLoading) {
  if (app.$refs.modelComponent) app.$refs.modelComponent.setDeepSearchLoading(isLoading);
}

// Door Global Functions (门型)
window.updateDoorFolders = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateFolders(data);
}
window.updateActiveDoorFolder = function(folderPath) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateActiveFolder(folderPath);
}
window.updateRecentDoorFolder = function(folderPath) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateRecentFolder(folderPath);
}
window.updateDoorTotalInModel = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateTotalInModel(data);
}
window.updateDoorFavorites = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateFavorites(data);
}
window.updateDoorRecent = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateRecent(data);
}
window.updateDoorRecentChildFolder = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateRecentChildFolder(data);
}
window.updateDoorOnlineSources = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateOnlineSources(data);
}
window.updateDoorItems = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateItems(data);
}
window.addNewDoorItem = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.addNewItem(data);
}
window.updateRenamedDoorItem = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateRenamedItem(data);
}
window.forceRefreshDoorThumbnails = function() {
  if (app.$refs.doorComponent) app.$refs.doorComponent.forceRefreshThumbnails();
}
window.updateActiveDoor = function(isActive, path) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateActive(isActive, path);
}
window.updateSelectedDoors = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateSelected(data);
}
window.updateDeleteDoorItems = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateDeleteItems(data);
}
window.updateIsDriveDoor = function(isDrive) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateIsDrive(isDrive);
}
window.updateDoorShowAll = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateShowAll(data);
}
window.updateDeepSearchDoors = function(data) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.updateDeepSearchResults(data);
}
window.setDeepSearchLoadingDoors = function(isLoading) {
  if (app.$refs.doorComponent) app.$refs.doorComponent.setDeepSearchLoading(isLoading);
}

// Component Global Functions (构件)
window.updateComponentFolders = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateFolders(data);
}
window.updateActiveComponentFolder = function(folderPath) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateActiveFolder(folderPath);
}
window.updateRecentComponentFolder = function(folderPath) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateRecentFolder(folderPath);
}
window.updateComponentTotalInModel = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateTotalInModel(data);
}
window.updateComponentFavorites = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateFavorites(data);
}
window.updateComponentRecent = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateRecent(data);
}
window.updateComponentRecentChildFolder = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateRecentChildFolder(data);
}
window.updateComponentOnlineSources = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateOnlineSources(data);
}
window.updateComponentItems = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateItems(data);
}
window.addNewComponentItem = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.addNewItem(data);
}
window.updateRenamedComponentItem = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateRenamedItem(data);
}
window.forceRefreshComponentThumbnails = function() {
  if (app.$refs.componentComponent) app.$refs.componentComponent.forceRefreshThumbnails();
}
window.updateActiveComponent = function(isActive, path) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateActive(isActive, path);
}
window.updateSelectedComponents = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateSelected(data);
}
window.updateDeleteComponentItems = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateDeleteItems(data);
}
window.updateIsDriveComponent = function(isDrive) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateIsDrive(isDrive);
}
window.updateComponentShowAll = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateShowAll(data);
}
window.updateDeepSearchComponents = function(data) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.updateDeepSearchResults(data);
}
window.setDeepSearchLoadingComponents = function(isLoading) {
  if (app.$refs.componentComponent) app.$refs.componentComponent.setDeepSearchLoading(isLoading);
}

// Handle Global Functions (拉手)
window.updateHandleFolders = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateFolders(data);
}
window.updateActiveHandleFolder = function(folderPath) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateActiveFolder(folderPath);
}
window.updateRecentHandleFolder = function(folderPath) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateRecentFolder(folderPath);
}
window.updateHandleTotalInModel = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateTotalInModel(data);
}
window.updateHandleFavorites = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateFavorites(data);
}
window.updateHandleRecent = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateRecent(data);
}
window.updateHandleRecentChildFolder = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateRecentChildFolder(data);
}
window.updateHandleOnlineSources = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateOnlineSources(data);
}
window.updateHandleItems = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateItems(data);
}
window.addNewHandleItem = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.addNewItem(data);
}
window.updateRenamedHandleItem = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateRenamedItem(data);
}
window.forceRefreshHandleThumbnails = function() {
  if (app.$refs.handleComponent) app.$refs.handleComponent.forceRefreshThumbnails();
}
window.updateActiveHandle = function(isActive, path) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateActive(isActive, path);
}
window.updateSelectedHandles = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateSelected(data);
}
window.updateDeleteHandleItems = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateDeleteItems(data);
}
window.updateIsDriveHandle = function(isDrive) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateIsDrive(isDrive);
}
window.updateHandleShowAll = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateShowAll(data);
}
window.updateDeepSearchHandles = function(data) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.updateDeepSearchResults(data);
}
window.setDeepSearchLoadingHandles = function(isLoading) {
  if (app.$refs.handleComponent) app.$refs.handleComponent.setDeepSearchLoading(isLoading);
}

// Material Global Functions
window.updateMaterialFolders = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateFolders(data);
}
window.updateActiveMaterialFolder = function(folderPath) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateActiveFolder(folderPath);
}
window.updateRecentMaterialFolder = function(folderPath) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateRecentFolder(folderPath);
}
window.updateMaterialTotalInModel = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateTotalInModel(data);
}
window.updateMaterialFavorites = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateFavorites(data);
}
window.updateMaterialRecent = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateRecent(data);
}
window.updateMaterialRecentChildFolder = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateRecentChildFolder(data);
}
window.updateMaterialOnlineSources = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateOnlineSources(data);
}
window.updateMaterialItems = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateItems(data);
}
window.addNewMaterialItem = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.addNewItem(data);
}
window.updateSingleMaterialItem = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateSingleMaterialItem(data);
}
window.updateRenamedMaterialItem = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateRenamedItem(data);
}
window.forceRefreshMaterialThumbnails = function() {
  if (app.$refs.materialComponent) app.$refs.materialComponent.forceRefreshThumbnails();
}
window.updateSelectedMaterials = function(isActive) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateSelected(isActive);
}
window.updateDeleteMaterialItems = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateDeleteItems(data);
}
window.updateIsDriveMaterial = function(isDrive) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateIsDrive(isDrive);
}
window.updateDeepSearchMaterials = function(data) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateDeepSearchResults(data);
}
window.setDeepSearchLoadingMaterials = function(isLoading) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.setDeepSearchLoading(isLoading);
}
window.updateImagesFolderPath = function(totalImages) {
  if (app.$refs.materialComponent) app.$refs.materialComponent.updateImagesFolderPath(totalImages);
}