import _ from 'lodash'
/* eslint-disable
    camelcase,
    node/handle-callback-err,
    max-len,
    no-return-assign,
    no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
 * decaffeinate suggestions:
 * DS102: Remove unnecessary code created because of implicit returns
 * DS103: Rewrite code to no longer use __guard__
 * DS207: Consider shorter variations of null checks
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */
import App from '../../../base'
App.controller(
  'FileTreeController',
  function ($scope, $modal, ide, $rootScope) {
    $scope.openNewDocModal = reactBridgeParentFolderId =>
      $modal.open({
        templateUrl: 'newFileModalTemplate',
        controller: 'NewFileModalController',
        size: 'lg',
        resolve: {
          parent_folder() {
            if (reactBridgeParentFolderId) {
              return { id: reactBridgeParentFolderId }
            }
            return ide.fileTreeManager.getCurrentFolder()
          },
          projectFeatures() {
            return ide.$scope.project.features
          },
          type() {
            return 'doc'
          },
          userFeatures() {
            return ide.$scope.user.features
          }
        }
      })

    $scope.openNewFolderModal = () =>
      $modal.open({
        templateUrl: 'newFolderModalTemplate',
        controller: 'NewFolderModalController',
        resolve: {
          parent_folder() {
            return ide.fileTreeManager.getCurrentFolder()
          }
        }
      })

    $scope.openUploadFileModal = reactBridgeParentFolderId =>
      $modal.open({
        templateUrl: 'newFileModalTemplate',
        controller: 'NewFileModalController',
        size: 'lg',
        resolve: {
          projectFeatures() {
            return ide.$scope.project.features
          },
          parent_folder() {
            if (reactBridgeParentFolderId) {
              return { id: reactBridgeParentFolderId }
            }
            return ide.fileTreeManager.getCurrentFolder()
          },
          type() {
            return 'upload'
          },
          userFeatures() {
            return ide.$scope.user.features
          }
        }
      })

    if (
      window.showReactFileTree &&
      !window.FileTreeReactBridgeOpenNewDocModalListened
    ) {
      window.FileTreeReactBridgeOpenNewDocModalListened = true
      window.addEventListener(
        'FileTreeReactBridge.openNewDocModal',
        ({ detail }) => {
          if (detail.mode === 'upload') {
            $scope.openUploadFileModal(detail.parentFolderId)
          } else {
            $scope.openNewDocModal(detail.parentFolderId)
          }
        }
      )
    }

    $scope.orderByFoldersFirst = function (entity) {
      if ((entity != null ? entity.type : undefined) === 'folder') {
        return '0'
      }
      return '1'
    }

    $scope.startRenamingSelected = () => $scope.$broadcast('rename:selected')

    return ($scope.openDeleteModalForSelected = () =>
      $scope.$broadcast('delete:selected'))
  }
)

App.controller(
  'NewFolderModalController',
  function ($scope, ide, $modalInstance, $timeout, parent_folder) {
    $scope.inputs = { name: 'name' }
    $scope.state = { inflight: false }

    $modalInstance.opened.then(() =>
      $timeout(() => $scope.$broadcast('open'), 200)
    )

    $scope.create = function () {
      const { name } = $scope.inputs
      if (name == null || name.length === 0) {
        return
      }
      $scope.state.inflight = true
      return ide.fileTreeManager
        .createFolder(name, $scope.parent_folder)
        .then(function () {
          $scope.state.inflight = false
          return $modalInstance.dismiss('done')
        })
        .catch(function (response) {
          const { data } = response
          $scope.error = data
          return ($scope.state.inflight = false)
        })
    }

    return ($scope.cancel = () => $modalInstance.dismiss('cancel'))
  }
)

App.controller(
  'DuplicateFileModalController',
  function ($scope, $modalInstance, fileName) {
    $scope.fileName = fileName
    $scope.cancel = () => $modalInstance.dismiss('cancel')
  }
)

App.controller(
  'NewFileModalController',
  function (
    $scope,
    ide,
    type,
    parent_folder,
    $modalInstance,
    eventTracking,
    projectFeatures,
    userFeatures
  ) {
    $scope.file_count = ide.fileTreeManager.getFullCount()
    $scope.type = type
    $scope.parent_folder = parent_folder
    $scope.state = {
      inflight: false,
      valid: true
    }
    $scope.cancel = () => $modalInstance.dismiss('cancel')
    $scope.create = () => $scope.$broadcast('create')

    const hasMendeleyFeature =
      (projectFeatures && projectFeatures.references) ||
      (projectFeatures && projectFeatures.mendeley) ||
      (userFeatures && userFeatures.references) ||
      (userFeatures && userFeatures.mendeley)

    const hasZoteroFeature =
      (projectFeatures && projectFeatures.references) ||
      (projectFeatures && projectFeatures.zotero) ||
      (userFeatures && userFeatures.references) ||
      (userFeatures && userFeatures.zotero)

    $scope.$watch('type', function () {
      if ($scope.type === 'mendeley' && !hasMendeleyFeature) {
        eventTracking.send(
          'subscription-funnel',
          'editor-click-feature',
          $scope.type
        )
      }
      if ($scope.type === 'zotero' && !hasZoteroFeature) {
        eventTracking.send(
          'subscription-funnel',
          'editor-click-feature',
          $scope.type
        )
      }
    })
    $scope.$on('done', (e, opts = {}) => {
      const isBibFile = opts.name && /^.*\.bib$/.test(opts.name)
      if (opts.shouldReindexReferences || isBibFile) {
        ide.$scope.$emit('references:should-reindex', {})
      }
      $modalInstance.dismiss('done')
    })

    if (
      window.showReactFileTree &&
      !window.FileTreeReactBridgeOpenNewFileModalListened
    ) {
      window.FileTreeReactBridgeOpenNewFileModalListened = true
      window.addEventListener(
        'FileTreeReactBridge.openNewFileModal',
        ({ detail }) => {
          if (detail.done) {
            ide.$scope.FileTreeReactBridgePromise.resolve()
          }
          if (detail.error) {
            ide.$scope.FileTreeReactBridgePromise.reject(detail)
          }
        }
      )
    }
  }
)

App.controller('NewDocModalController', function ($scope, ide, $timeout) {
  $scope.inputs = { name: 'name.tex' }

  $timeout(() => $scope.$broadcast('open'), 200)

  return $scope.$on('create', function () {
    const { name } = $scope.inputs
    if (name == null || name.length === 0) {
      return
    }
    $scope.state.inflight = true
    return ide.fileTreeManager
      .createDoc(name, $scope.parent_folder)
      .then(function () {
        $scope.state.inflight = false
        return $scope.$emit('done')
      })
      .catch(function (response) {
        const { data } = response
        $scope.error = data
        $scope.state.inflight = false
      })
      .finally(function () {
        if (!$scope.$$phase) {
          $scope.$apply()
        }
      })
  })
})

App.controller(
  'UploadFileModalController',
  function ($scope, $rootScope, ide, $timeout, $window) {
    $scope.parent_folder_id =
      $scope.parent_folder != null ? $scope.parent_folder.id : undefined
    $scope.project_id = ide.project_id
    $scope.tooManyFiles = false
    $scope.rateLimitHit = false
    $scope.secondsToRedirect = 10
    $scope.notLoggedIn = false
    $scope.conflicts = []
    $scope.control = {}

    const needToLogBackIn = function () {
      $scope.notLoggedIn = true
      var decreseTimeout = () =>
        $timeout(function () {
          if ($scope.secondsToRedirect === 0) {
            return ($window.location.href = `/login?redir=/project/${ide.project_id}`)
          } else {
            decreseTimeout()
            return ($scope.secondsToRedirect = $scope.secondsToRedirect - 1)
          }
        }, 1000)

      return decreseTimeout()
    }

    $scope.max_files = 40
    $scope.onComplete = (error, name, response) =>
      $timeout(function () {
        uploadCount--
        if (response.success) {
          $rootScope.$broadcast('file:upload:complete', response)
        }
        if (uploadCount === 0 && response != null && response.success) {
          return $scope.$emit('done', { name: name })
        }
      }, 250)

    $scope.onValidateBatch = function (files) {
      if (files.length > $scope.max_files) {
        $timeout(() => ($scope.tooManyFiles = true), 1)
        return false
      } else {
        return true
      }
    }

    $scope.onError = function (id, name, reason) {
      console.log(id, name, reason)
      if (reason.indexOf('429') !== -1) {
        return ($scope.rateLimitHit = true)
      } else if (reason.indexOf('403') !== -1) {
        return needToLogBackIn()
      }
    }

    let _uploadTimer = null
    const uploadIfNoConflicts = function () {
      if ($scope.conflicts.length === 0) {
        return $scope.doUpload()
      }
    }

    var uploadCount = 0
    $scope.onSubmit = function (id, name) {
      uploadCount++
      if (ide.fileTreeManager.existsInFolder($scope.parent_folder_id, name)) {
        $scope.conflicts.push(name)
        $scope.$apply()
      }
      if (_uploadTimer == null) {
        _uploadTimer = setTimeout(function () {
          _uploadTimer = null
          return uploadIfNoConflicts()
        }, 0)
      }
      return true
    }

    $scope.onCancel = function (id, name) {
      uploadCount--
      const index = $scope.conflicts.indexOf(name)
      if (index > -1) {
        $scope.conflicts.splice(index, 1)
      }
      $scope.$apply()
      return uploadIfNoConflicts()
    }

    return ($scope.doUpload = () =>
      __guard__($scope.control != null ? $scope.control.q : undefined, x =>
        x.uploadStoredFiles()
      ))
  }
)

App.controller(
  'ProjectLinkedFileModalController',
  function ($scope, ide, $timeout) {
    $scope.data = {
      projects: null, // or []
      selectedProjectId: null,
      projectEntities: null, // or []
      projectOutputFiles: null, // or []
      selectedProjectEntity: null,
      selectedProjectOutputFile: null,
      buildId: null,
      name: null
    }
    $scope.state.inFlight = {
      projects: false,
      entities: false,
      compile: false
    }
    $scope.state.isOutputFilesMode = false
    $scope.state.error = false

    $scope.$watch('data.selectedProjectId', function (newVal, oldVal) {
      if (!newVal) {
        return
      }
      $scope.data.selectedProjectEntity = null
      $scope.data.selectedProjectOutputFile = null
      if ($scope.state.isOutputFilesMode) {
        return $scope.compileProjectAndGetOutputFiles(
          $scope.data.selectedProjectId
        )
      } else {
        return $scope.getProjectEntities($scope.data.selectedProjectId)
      }
    })

    $scope.$watch('state.isOutputFilesMode', function (newVal, oldVal) {
      if (!newVal && !oldVal) {
        return
      }
      $scope.data.selectedProjectOutputFile = null
      if (newVal === true) {
        return $scope.compileProjectAndGetOutputFiles(
          $scope.data.selectedProjectId
        )
      } else {
        return $scope.getProjectEntities($scope.data.selectedProjectId)
      }
    })

    // auto-set filename based on selected file
    $scope.$watch('data.selectedProjectEntity', function (newVal, oldVal) {
      if (!newVal) {
        return
      }
      const fileName = newVal.split('/').reverse()[0]
      if (fileName) {
        $scope.data.name = fileName
      }
    })

    // auto-set filename based on selected file
    $scope.$watch('data.selectedProjectOutputFile', function (newVal, oldVal) {
      if (!newVal) {
        return
      }
      if (newVal === 'output.pdf') {
        const project = _.find(
          $scope.data.projects,
          p => p._id === $scope.data.selectedProjectId
        )
        $scope.data.name =
          (project != null ? project.name : undefined) != null
            ? `${project.name}.pdf`
            : 'output.pdf'
      } else {
        const fileName = newVal.split('/').reverse()[0]
        if (fileName) {
          $scope.data.name = fileName
        }
      }
    })

    const _setInFlight = type => ($scope.state.inFlight[type] = true)

    const _reset = function (opts) {
      const isError = opts.err === true
      const { inFlight } = $scope.state
      inFlight.projects = inFlight.entities = inFlight.compile = false
      $scope.state.inflight = false
      return ($scope.state.error = isError)
    }

    $scope.toggleOutputFilesMode = function () {
      if (!$scope.data.selectedProjectId) {
        return
      }
      return ($scope.state.isOutputFilesMode = !$scope.state.isOutputFilesMode)
    }

    $scope.shouldEnableProjectSelect = function () {
      const { state, data } = $scope
      return !state.inFlight.projects && data.projects
    }

    $scope.hasNoProjects = function () {
      const { state, data } = $scope
      return (
        !state.inFlight.projects &&
        (data.projects == null || data.projects.length === 0)
      )
    }

    $scope.shouldEnableProjectEntitySelect = function () {
      const { state, data } = $scope
      return (
        !state.inFlight.projects &&
        !state.inFlight.entities &&
        data.projects &&
        data.selectedProjectId
      )
    }

    $scope.shouldEnableProjectOutputFileSelect = function () {
      const { state, data } = $scope
      return (
        !state.inFlight.projects &&
        !state.inFlight.compile &&
        data.projects &&
        data.selectedProjectId
      )
    }

    const validate = function () {
      const { state } = $scope
      const { data } = $scope
      $scope.state.valid =
        !state.inFlight.projects &&
        !state.inFlight.entities &&
        data.projects &&
        data.selectedProjectId &&
        ((!$scope.state.isOutputFilesMode &&
          data.projectEntities &&
          data.selectedProjectEntity) ||
          ($scope.state.isOutputFilesMode &&
            data.projectOutputFiles &&
            data.selectedProjectOutputFile)) &&
        data.name
    }
    $scope.$watch('state', validate, true)
    $scope.$watch('data', validate, true)

    $scope.getUserProjects = function () {
      _setInFlight('projects')
      return ide.$http
        .get('/user/projects', {
          _csrf: window.csrfToken
        })
        .then(function (resp) {
          $scope.data.projectEntities = null
          $scope.data.projects = resp.data.projects.filter(
            p => p._id !== ide.project_id
          )
          return _reset({ err: false })
        })
        .catch(err => _reset({ err: true }))
    }

    $scope.getProjectEntities = project_id => {
      _setInFlight('entities')
      return ide.$http
        .get(`/project/${project_id}/entities`, {
          _csrf: window.csrfToken
        })
        .then(function (resp) {
          if ($scope.data.selectedProjectId === resp.data.project_id) {
            $scope.data.projectEntities = resp.data.entities
            return _reset({ err: false })
          }
        })
        .catch(err => _reset({ err: true }))
    }

    $scope.compileProjectAndGetOutputFiles = project_id => {
      _setInFlight('compile')
      return ide.$http
        .post(`/project/${project_id}/compile`, {
          check: 'silent',
          draft: false,
          incrementalCompilesEnabled: false,
          _csrf: window.csrfToken
        })
        .then(function (resp) {
          if (resp.data.status === 'success') {
            const filteredFiles = resp.data.outputFiles.filter(f =>
              f.path.match(/.*\.(pdf|png|jpeg|jpg|gif)/)
            )
            $scope.data.projectOutputFiles = filteredFiles
            $scope.data.buildId = __guard__(
              filteredFiles != null ? filteredFiles[0] : undefined,
              x => x.build
            )
            console.log('>> build_id', $scope.data.buildId)
            return _reset({ err: false })
          } else {
            $scope.data.projectOutputFiles = null
            return _reset({ err: true })
          }
        })
        .catch(function (err) {
          console.error(err)
          return _reset({ err: true })
        })
    }

    $scope.init = () => $scope.getUserProjects()
    $timeout($scope.init, 0)

    return $scope.$on('create', function () {
      let payload, provider
      const projectId = $scope.data.selectedProjectId
      const { name } = $scope.data
      if ($scope.state.isOutputFilesMode) {
        provider = 'project_output_file'
        payload = {
          source_project_id: projectId,
          source_output_file_path: $scope.data.selectedProjectOutputFile,
          build_id: $scope.data.buildId
        }
      } else {
        provider = 'project_file'
        payload = {
          source_project_id: projectId,
          source_entity_path: $scope.data.selectedProjectEntity
        }
      }
      _setInFlight('create')
      ide.fileTreeManager
        .createLinkedFile(name, $scope.parent_folder, provider, payload)
        .then(function () {
          _reset({ err: false })
          return $scope.$emit('done', { name: name })
        })
        .catch(function (response) {
          const { data } = response
          $scope.error = data
        })
        .finally(function () {
          if (!$scope.$$phase) {
            $scope.$apply()
          }
        })
    })
  }
)

export default App.controller(
  'UrlLinkedFileModalController',
  function ($scope, ide, $timeout) {
    $scope.inputs = {
      name: '',
      url: ''
    }
    $scope.nameChangedByUser = false

    $timeout(() => $scope.$broadcast('open'), 200)

    const validate = function () {
      const { name, url } = $scope.inputs
      if (name == null || name.length === 0) {
        return ($scope.state.valid = false)
      } else if (url == null || url.length === 0) {
        return ($scope.state.valid = false)
      } else {
        return ($scope.state.valid = true)
      }
    }
    $scope.$watch('inputs.name', validate)
    $scope.$watch('inputs.url', validate)

    $scope.$watch('inputs.url', function (url) {
      if (url != null && url !== '' && !$scope.nameChangedByUser) {
        url = url.replace('://', '') // Ignore http:// etc
        const parts = url.split('/').reverse()
        if (parts.length > 1) {
          // Wait for at one /
          return ($scope.inputs.name = parts[0])
        }
      }
    })

    return $scope.$on('create', function () {
      const { name, url } = $scope.inputs
      if (name == null || name.length === 0) {
        return
      }
      if (url == null || url.length === 0) {
        return
      }
      $scope.state.inflight = true
      return ide.fileTreeManager
        .createLinkedFile(name, $scope.parent_folder, 'url', { url })
        .then(function () {
          $scope.state.inflight = false
          return $scope.$emit('done', { name: name })
        })
        .catch(function (response) {
          const { data } = response
          $scope.error = data
          return ($scope.state.inflight = false)
        })
        .finally(function () {
          if (!$scope.$$phase) {
            $scope.$apply()
          }
        })
    })
  }
)

function __guard__(value, transform) {
  return typeof value !== 'undefined' && value !== null
    ? transform(value)
    : undefined
}
