text: 'use strict'
  import { RunTab, makeUdapp } from './app/udapp'
  import { RemixEngine } from './remixEngine'
  import { RemixAppManager } from './remixAppManager'
  import { ThemeModule } from './app/tabs/theme-module'
  import { NetworkModule } from './app/tabs/network-module'
  import { Web3ProviderModule } from './app/tabs/web3-provider'
  import { SidePanel } from './app/components/side-panel'
  import { HiddenPanel } from './app/components/hidden-panel'
  import { VerticalIcons } from './app/components/vertical-icons'
  import { LandingPage } from './app/ui/landing-page/landing-page'
  import { MainPanel } from './app/components/main-panel'
  import { PermissionHandlerPlugin } from './app/plugins/permission-handler-plugin'
  import { AstWalker } from '@remix-project/remix-astwalker'
  
  import { WalkthroughService } from './walkthroughService'
  
  import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, EditorContextListener, GistHandler } from '@remix-project/core-plugin'
  
  import Registry from './app/state/registry'
  import { ConfigPlugin } from './app/plugins/config'
  import { StoragePlugin } from './app/plugins/storage'
  import { Layout } from './app/panels/layout'
  import { NotificationPlugin } from './app/plugins/notification'
  import { Blockchain } from './blockchain/blockchain.js'
  import { HardhatProvider } from './app/tabs/hardhat-provider'
  
  const isElectron = require('is-electron')
  
  const remixLib = require('@remix-project/remix-lib')
  
  import { QueryParams } from '@remix-project/remix-lib'
  const Storage = remixLib.Storage
  const RemixDProvider = require('./app/files/remixDProvider')
  const Config = require('./config')
  
  const FileManager = require('./app/files/fileManager')
  const FileProvider = require('./app/files/fileProvider')
  const DGitProvider = require('./app/files/dgitProvider')
  const WorkspaceFileProvider = require('./app/files/workspaceFileProvider')
  
  const PluginManagerComponent = require('./app/components/plugin-manager-component')
  
  const CompileTab = require('./app/tabs/compile-tab')
  const SettingsTab = require('./app/tabs/settings-tab')
  const AnalysisTab = require('./app/tabs/analysis-tab')
  const { DebuggerTab } = require('./app/tabs/debugger-tab')
  const TestTab = require('./app/tabs/test-tab')
  const FilePanel = require('./app/panels/file-panel')
  const Editor = require('./app/editor/editor')
  const Terminal = require('./app/panels/terminal')
  const { TabProxy } = require('./app/panels/tab-proxy.js')
  
  class AppComponent {
    constructor () {
      this.appManager = new RemixAppManager({})
      this.queryParams = new QueryParams()
      this._components = {}
      // setup storage
      const configStorage = new Storage('config-v0.8:')
  
      // load app config
      const config = new Config(configStorage)
      Registry.getInstance().put({ api: config, name: 'config' })
  
      // load file system
      this._components.filesProviders = {}
      this._components.filesProviders.browser = new FileProvider('browser')
      Registry.getInstance().put({
        api: this._components.filesProviders.browser,
        name: 'fileproviders/browser'
      })
      this._components.filesProviders.localhost = new RemixDProvider(
        this.appManager
      )
      Registry.getInstance().put({
        api: this._components.filesProviders.localhost,
        name: 'fileproviders/localhost'
      })
      this._components.filesProviders.workspace = new WorkspaceFileProvider()
      Registry.getInstance().put({
        api: this._components.filesProviders.workspace,
        name: 'fileproviders/workspace'
      })
  
      Registry.getInstance().put({
        api: this._components.filesProviders,
        name: 'fileproviders'
      })
    }
  
    async run () {
      // APP_MANAGER
      const appManager = this.appManager
      const pluginLoader = this.appManager.pluginLoader
      this.panels = {}
      this.workspace = pluginLoader.get()
      this.engine = new RemixEngine()
      this.engine.register(appManager);
  
  
  
      const matomoDomains = {
        'remix-alpha.ethereum.org': 27,
        'remix-beta.ethereum.org': 25,
        'remix.ethereum.org': 23
      }
      this.showMatamo =
        matomoDomains[window.location.hostname] &&
        !Registry.getInstance()
          .get('config')
          .api.exists('settings/matomo-analytics')
      this.walkthroughService = new WalkthroughService(
        appManager,
        this.showMatamo
      )
  
      const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080']
      // workaround for Electron support
      if (!isElectron() && !hosts.includes(window.location.host)) {
        // Oops! Accidentally trigger refresh or bookmark.
        window.onbeforeunload = function () {
          return 'Are you sure you want to leave?'
        }
      }
  
      // SERVICES
      // ----------------- gist service ---------------------------------
      this.gistHandler = new GistHandler()
      // ----------------- theme service ---------------------------------
      this.themeModule = new ThemeModule()
      Registry.getInstance().put({ api: this.themeModule, name: 'themeModule' })
  
      // ----------------- editor service ----------------------------
      const editor = new Editor() // wrapper around ace editor
      Registry.getInstance().put({ api: editor, name: 'editor' })
      editor.event.register('requiringToSaveCurrentfile', () =>
        fileManager.saveCurrentFile()
      )
  
      // ----------------- fileManager service ----------------------------
      const fileManager = new FileManager(editor, appManager)
      Registry.getInstance().put({ api: fileManager, name: 'filemanager' })
      // ----------------- dGit provider ---------------------------------
      const dGitProvider = new DGitProvider()
  
      // ----------------- Storage plugin ---------------------------------
      const storagePlugin = new StoragePlugin()
  
      // ----------------- import content service ------------------------
      const contentImport = new CompilerImports()
  
      const blockchain = new Blockchain(Registry.getInstance().get('config').api)
  
      // ----------------- compilation metadata generation service ---------
      const compilerMetadataGenerator = new CompilerMetadata()
      // ----------------- compilation result service (can keep track of compilation results) ----------------------------
      const compilersArtefacts = new CompilerArtefacts() // store all the compilation results (key represent a compiler name)
      Registry.getInstance().put({
        api: compilersArtefacts,
        name: 'compilersartefacts'
      })
  
      // service which fetch contract artifacts from sourve-verify, put artifacts in remix and compile it
      const fetchAndCompile = new FetchAndCompile()
      // ----------------- network service (resolve network id / name) -----
      const networkModule = new NetworkModule(blockchain)
      // ----------------- represent the current selected web3 provider ----
      const web3Provider = new Web3ProviderModule(blockchain)
      const hardhatProvider = new HardhatProvider(blockchain)
      // ----------------- convert offset to line/column service -----------
      const offsetToLineColumnConverter = new OffsetToLineColumnConverter()
      Registry.getInstance().put({
        api: offsetToLineColumnConverter,
        name: 'offsettolinecolumnconverter'
      })
  
      // -------------------Terminal----------------------------------------
      makeUdapp(blockchain, compilersArtefacts, domEl => terminal.logHtml(domEl))
      const terminal = new Terminal(
        { appManager, blockchain },
        {
          getPosition: event => {
            const limitUp = 36
            const limitDown = 20
            const height = window.innerHeight
            let newpos = event.pageY < limitUp ? limitUp : event.pageY
            newpos = newpos < height - limitDown ? newpos : height - limitDown
            return height - newpos
          }
        }
      )
      const contextualListener = new EditorContextListener(new AstWalker())
  
      this.notification = new NotificationPlugin()
  
      const configPlugin = new ConfigPlugin()
      this.layout = new Layout()
      
      const permissionHandler = new PermissionHandlerPlugin()
  
      this.engine.register([
        permissionHandler,
        this.layout,
        this.notification,
        this.gistHandler,
        configPlugin,
        blockchain,
        contentImport,
        this.themeModule,
        editor,
        fileManager,
        compilerMetadataGenerator,
        compilersArtefacts,
        networkModule,
        offsetToLineColumnConverter,
        contextualListener,
        terminal,
        web3Provider,
        fetchAndCompile,
        dGitProvider,
        storagePlugin,
        hardhatProvider,
        this.walkthroughService
      ])
  
      // LAYOUT & SYSTEM VIEWS
      const appPanel = new MainPanel()
      Registry.getInstance().put({ api: this.mainview, name: 'mainview' })
      const tabProxy = new TabProxy(fileManager, editor)
      this.engine.register([appPanel, tabProxy])
  
      // those views depend on app_manager
      this.menuicons = new VerticalIcons()
      this.sidePanel = new SidePanel()
      this.hiddenPanel = new HiddenPanel()
  
      const pluginManagerComponent = new PluginManagerComponent(
        appManager,
        this.engine
      )
      const filePanel = new FilePanel(appManager)
      const landingPage = new LandingPage(
        appManager,
        this.menuicons,
        fileManager,
        filePanel,
        contentImport
      )
      this.settings = new SettingsTab(
        Registry.getInstance().get('config').api,
        editor,
        appManager
      )
  
      this.engine.register([
        this.menuicons,
        landingPage,
        this.hiddenPanel,
        this.sidePanel,
        filePanel,
        pluginManagerComponent,
        this.settings
      ])
  
      // CONTENT VIEWS & DEFAULT PLUGINS
      const compileTab = new CompileTab(
        Registry.getInstance().get('config').api,
        Registry.getInstance().get('filemanager').api
      )
      const run = new RunTab(
        blockchain,
        Registry.getInstance().get('config').api,
        Registry.getInstance().get('filemanager').api,
        Registry.getInstance().get('editor').api,
        filePanel,
        Registry.getInstance().get('compilersartefacts').api,
        networkModule,
        Registry.getInstance().get('fileproviders/browser').api
      )
      const analysis = new AnalysisTab()
      const debug = new DebuggerTab()
      const test = new TestTab(
        Registry.getInstance().get('filemanager').api,
        Registry.getInstance().get('offsettolinecolumnconverter').api,
        filePanel,
        compileTab,
        appManager,
        contentImport
      )
  
      this.engine.register([
        compileTab,
        run,
        debug,
        analysis,
        test,
        filePanel.remixdHandle,
        filePanel.gitHandle,
        filePanel.hardhatHandle,
        filePanel.slitherHandle
      ])
  
      this.layout.panels = {
        tabs: { plugin: tabProxy, active: true },
        editor: { plugin: editor, active: true },
        main: { plugin: appPanel, active: false },
        terminal: { plugin: terminal, active: true, minimized: false }
      }
    }
  
    async activate () {
      const queryParams = new QueryParams()
      const params = queryParams.get()
      
      if (isElectron()) {
        this.appManager.activatePlugin('remixd')
      }
  
      try {
        this.engine.register(await this.appManager.registeredPlugins())
      } catch (e) {
        console.log("couldn't register iframe plugins", e.message)
      }
      await this.appManager.activatePlugin(['layout'])
      await this.appManager.activatePlugin(['notification'])
      await this.appManager.activatePlugin(['editor'])
      await this.appManager.activatePlugin(['permissionhandler', 'theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
      await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
      await this.appManager.activatePlugin(['sidePanel']) // activating  host plugin separately
      await this.appManager.activatePlugin(['home'])
      await this.appManager.activatePlugin(['settings', 'config'])
      await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler'])
      await this.appManager.activatePlugin(['settings'])
      await this.appManager.activatePlugin(['walkthrough','storage'])
  
      this.appManager.on(
        'filePanel',
        'workspaceInitializationCompleted',
        async () => {
          await this.appManager.registerContextMenuItems()
        }
      )
  
      await this.appManager.activatePlugin(['filePanel'])
      // Set workspace after initial activation
      this.appManager.on('editor', 'editorMounted', () => {
        if (Array.isArray(this.workspace)) {
          this.appManager
            .activatePlugin(this.workspace)
            .then(async () => {
              try {
                if (params.deactivate) {
                  await this.appManager.deactivatePlugin(
                    params.deactivate.split(',')
                  )
                }
              } catch (e) {
                console.log(e)
              }
              if (params.code) {
                // if code is given in url we focus on solidity plugin
                this.menuicons.select('solidity')
              } else {
                // If plugins are loaded from the URL params, we focus on the last one.
                if (
                  this.appManager.pluginLoader.current === 'queryParams' &&
                  this.workspace.length > 0
                ) { this.menuicons.select(this.workspace[this.workspace.length - 1]) }
              }
  
              if (params.call) {
                const callDetails = params.call.split('//')
                if (callDetails.length > 1) {
                  this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} ...`)
                  // @todo(remove the timeout when activatePlugin is on 0.3.0)
                  this.appManager.call(...callDetails).catch(console.error)
                }
              }
            })
            .catch(console.error)
        }
      })
      // activate solidity plugin
      this.appManager.activatePlugin(['solidity', 'udapp'])
      // Load and start the service who manager layout and frame
    }
  }
  
  export default AppComponent
  