// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// If directory files changes too often, don't rescan directory more than once
// per specified interval
var SIMULTANEOUS_RESCAN_INTERVAL = 500;
// Used for operations that require almost instant rescan.
var SHORT_RESCAN_INTERVAL = 100;

/**
 * Data model of the file manager.
 *
 * @constructor
 * @extends {cr.EventTarget}
 *
 * @param {boolean} singleSelection True if only one file could be selected
 *                                  at the time.
 * @param {FileFilter} fileFilter Instance of FileFilter.
 * @param {!MetadataModel} metadataModel Metadata model.
 *     service.
 * @param {!VolumeManager} volumeManager The volume manager.
 * @param {!FileOperationManager} fileOperationManager File operation manager.
 */
function DirectoryModel(
    singleSelection, fileFilter, metadataModel, volumeManager,
    fileOperationManager) {
  this.fileListSelection_ = singleSelection ?
      new FileListSingleSelectionModel() : new FileListSelectionModel();

  this.runningScan_ = null;
  this.pendingScan_ = null;
  this.rescanTime_ = null;
  this.scanFailures_ = 0;
  this.changeDirectorySequence_ = 0;

  /**
   * @private {boolean}
   */
  this.ignoreCurrentDirectoryDeletion_ = false;

  this.directoryChangeQueue_ = new AsyncUtil.Queue();
  this.rescanAggregator_ = new AsyncUtil.Aggregator(
      this.rescanSoon.bind(this, true), 500);

  this.fileFilter_ = fileFilter;
  this.fileFilter_.addEventListener('changed',
                                    this.onFilterChanged_.bind(this));

  this.currentFileListContext_ =
      new FileListContext(fileFilter, metadataModel, volumeManager);
  this.currentDirContents_ =
      DirectoryContents.createForDirectory(this.currentFileListContext_, null);
  /**
   * Empty file list which is used as a dummy for inactive view of file list.
   * @private {!FileListModel}
   */
  this.emptyFileList_ = new FileListModel(metadataModel);

  this.metadataModel_ = metadataModel;

  this.volumeManager_ = volumeManager;
  this.volumeManager_.volumeInfoList.addEventListener(
      'splice', this.onVolumeInfoListUpdated_.bind(this));

  /**
   * File watcher.
   * @private {!FileWatcher}
   * @const
   */
  this.fileWatcher_ = new FileWatcher();
  this.fileWatcher_.addEventListener(
      'watcher-directory-changed',
      this.onWatcherDirectoryChanged_.bind(this));
  util.addEventListenerToBackgroundComponent(
      fileOperationManager,
      'entries-changed',
      this.onEntriesChanged_.bind(this));

  /** @private {string} */
  this.lastSearchQuery_ = '';

  /** @private {FilesAppDirEntry} */
  this.myFilesEntry_ = null;
}

/**
 * DirectoryModel extends cr.EventTarget.
 */
DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype;

/**
 * Disposes the directory model by removing file watchers.
 */
DirectoryModel.prototype.dispose = function() {
  this.fileWatcher_.dispose();
};

/**
 * @return {FileListModel} Files in the current directory.
 */
DirectoryModel.prototype.getFileList = function() {
  return this.currentFileListContext_.fileList;
};

/**
 * @return {!FileListModel} File list which is always empty.
 */
DirectoryModel.prototype.getEmptyFileList = function() {
  return this.emptyFileList_;
};

/**
 * @return {!FileListSelectionModel|!FileListSingleSelectionModel} Selection
 * in the fileList.
 */
DirectoryModel.prototype.getFileListSelection = function() {
  return this.fileListSelection_;
};

/**
 * Obtains current volume information.
 * @return {VolumeInfo}
 */
DirectoryModel.prototype.getCurrentVolumeInfo = function() {
  var entry = this.getCurrentDirEntry();
  if (!entry) {
    return null;
  }
  return this.volumeManager_.getVolumeInfo(entry);
};

/**
 * @return {?VolumeManagerCommon.RootType} Root type of current root, or null if
 *     not found.
 */
DirectoryModel.prototype.getCurrentRootType = function() {
  var entry = this.currentDirContents_.getDirectoryEntry();
  if (!entry) {
    return null;
  }

  var locationInfo = this.volumeManager_.getLocationInfo(entry);
  if (!locationInfo) {
    return null;
  }

  return locationInfo.rootType;
};

/**
 * Metadata property names that are expected to be Prefetched.
 * @return {!Array<string>}
 */
DirectoryModel.prototype.getPrefetchPropertyNames = function() {
  return this.currentFileListContext_.prefetchPropertyNames;
};

/**
 * @return {boolean} True if the current directory is read only. If there is
 *     no entry set, then returns true.
 */
DirectoryModel.prototype.isReadOnly = function() {
  var currentDirEntry = this.getCurrentDirEntry();
  if (currentDirEntry) {
    var locationInfo = this.volumeManager_.getLocationInfo(currentDirEntry);
    if (locationInfo) {
      return locationInfo.isReadOnly;
    }
  }
  return true;
};

/**
 * @return {boolean} True if the a scan is active.
 */
DirectoryModel.prototype.isScanning = function() {
  return this.currentDirContents_.isScanning();
};

/**
 * @return {boolean} True if search is in progress.
 */
DirectoryModel.prototype.isSearching = function() {
  return this.currentDirContents_.isSearch();
};

/**
 * @return {boolean} True if it's on Drive.
 */
DirectoryModel.prototype.isOnDrive = function() {
  return this.isCurrentRootVolumeType_(VolumeManagerCommon.VolumeType.DRIVE);
};

/**
 * @return {boolean} True if it's on MTP volume.
 */
DirectoryModel.prototype.isOnMTP = function() {
  return this.isCurrentRootVolumeType_(VolumeManagerCommon.VolumeType.MTP);
};

/**
 * @param {VolumeManagerCommon.VolumeType} volumeType Volume Type
 * @return {boolean} True if current root volume type is equal to specified
 *     volume type.
 * @private
 */
DirectoryModel.prototype.isCurrentRootVolumeType_ = function(volumeType) {
  var rootType = this.getCurrentRootType();
  return rootType != null && rootType != VolumeManagerCommon.RootType.RECENT &&
      VolumeManagerCommon.getVolumeTypeFromRootType(rootType) === volumeType;
};

/**
 * Updates the selection by using the updateFunc and publish the change event.
 * If updateFunc returns true, it force to dispatch the change event even if the
 * selection index is not changed.
 *
 * @param {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} selection
 *     Selection to be updated.
 * @param {function(): boolean} updateFunc Function updating the selection.
 * @private
 */
DirectoryModel.prototype.updateSelectionAndPublishEvent_ =
    function(selection, updateFunc) {
  // Begin change.
  selection.beginChange();

  // If dispatchNeeded is true, we should ensure the change event is
  // dispatched.
  var dispatchNeeded = updateFunc();

  // Check if the change event is dispatched in the endChange function
  // or not.
  var eventDispatched = function() {
    dispatchNeeded = false;
  };
  selection.addEventListener('change', eventDispatched);
  selection.endChange();
  selection.removeEventListener('change', eventDispatched);

  // If the change event have been already dispatched, dispatchNeeded is false.
  if (dispatchNeeded) {
    var event = new Event('change');
    // The selection status (selected or not) is not changed because
    // this event is caused by the change of selected item.
    event.changes = [];
    selection.dispatchEvent(event);
  }
};

/**
 * Sets to ignore current directory deletion. This method is used to prevent
 * going up to the volume root with the deletion of current directory by rename
 * operation in directory tree.
 * @param {boolean} value True to ignore current directory deletion.
 */
DirectoryModel.prototype.setIgnoringCurrentDirectoryDeletion = function(value) {
  this.ignoreCurrentDirectoryDeletion_ = value;
};

/**
 * Invoked when a change in the directory is detected by the watcher.
 * @param {Event} event Event object.
 * @private
 */
DirectoryModel.prototype.onWatcherDirectoryChanged_ = function(event) {
  var directoryEntry = this.getCurrentDirEntry();

  if (!this.ignoreCurrentDirectoryDeletion_) {
    // If the change is deletion of currentDir, move up to its parent directory.
    directoryEntry.getDirectory(
        directoryEntry.fullPath, {create: false}, function() {},
        function() {
          var volumeInfo =
              this.volumeManager_.getVolumeInfo(assert(directoryEntry));
          if (volumeInfo) {
            volumeInfo.resolveDisplayRoot().then(function(displayRoot) {
              this.changeDirectoryEntry(displayRoot);
            }.bind(this));
          }
        }.bind(this));
  }

  if (event.changedFiles) {
    var addedOrUpdatedFileUrls = [];
    var deletedFileUrls = [];
    event.changedFiles.forEach(function(change) {
      if (change.changes.length === 1 && change.changes[0] === 'delete') {
        deletedFileUrls.push(change.url);
      } else {
        addedOrUpdatedFileUrls.push(change.url);
      }
    });

    util.URLsToEntries(addedOrUpdatedFileUrls).then(function(result) {
      deletedFileUrls = deletedFileUrls.concat(result.failureUrls);

      // Passing the resolved entries and failed URLs as the removed files.
      // The URLs are removed files and they chan't be resolved.
      this.partialUpdate_(result.entries, deletedFileUrls);
    }.bind(this)).catch(function(error) {
      console.error('Error in proceeding the changed event.', error,
                    'Fallback to force-refresh');
      this.rescanAggregator_.run();
    }.bind(this));
  } else {
    // Invokes force refresh if the detailed information isn't provided.
    // This can occur very frequently (e.g. when copying files into Downlaods)
    // and rescan is heavy operation, so we keep some interval for each rescan.
    this.rescanAggregator_.run();
  }
};

/**
 * Invoked when filters are changed.
 * @private
 */
DirectoryModel.prototype.onFilterChanged_ = function() {
  const currentDirectory = this.getCurrentDirEntry();
  if (currentDirectory && util.isNativeEntry(currentDirectory) &&
      !this.fileFilter_.filter(
          /** @type {!DirectoryEntry} */ (currentDirectory))) {
    // If the current directory should be hidden in the new filter setting,
    // change the current directory to the current volume's root.
    const volumeInfo = this.volumeManager_.getVolumeInfo(currentDirectory);
    if (volumeInfo) {
      volumeInfo.resolveDisplayRoot().then(displayRoot => {
        this.changeDirectoryEntry(displayRoot);
      });
    }
  } else {
    this.rescanSoon(false);
  }
};

/**
 * Returns the filter.
 * @return {FileFilter} The file filter.
 */
DirectoryModel.prototype.getFileFilter = function() {
  return this.fileFilter_;
};

/**
 * @return {DirectoryEntry|FakeEntry|FilesAppDirEntry} Current directory.
 */
DirectoryModel.prototype.getCurrentDirEntry = function() {
  return this.currentDirContents_.getDirectoryEntry();
};

/**
 * @return {Array<Entry>} Array of selected entries.
 * @private
 */
DirectoryModel.prototype.getSelectedEntries_ = function() {
  var indexes = this.fileListSelection_.selectedIndexes;
  var fileList = this.getFileList();
  if (fileList) {
    return indexes.map(function(i) {
      return fileList.item(i);
    });
  }
  return [];
};

/**
 * @param {Array<Entry>} value List of selected entries.
 * @private
 */
DirectoryModel.prototype.setSelectedEntries_ = function(value) {
  var indexes = [];
  var fileList = this.getFileList();
  var urls = util.entriesToURLs(value);

  for (var i = 0; i < fileList.length; i++) {
    if (urls.indexOf(fileList.item(i).toURL()) !== -1) {
      indexes.push(i);
    }
  }
  this.fileListSelection_.selectedIndexes = indexes;
};

/**
 * @return {Entry} Lead entry.
 * @private
 */
DirectoryModel.prototype.getLeadEntry_ = function() {
  var index = this.fileListSelection_.leadIndex;
  return index >= 0 ?
      /** @type {Entry} */ (this.getFileList().item(index)) : null;
};

/**
 * @param {Entry} value The new lead entry.
 * @private
 */
DirectoryModel.prototype.setLeadEntry_ = function(value) {
  var fileList = this.getFileList();
  for (var i = 0; i < fileList.length; i++) {
    if (util.isSameEntry(/** @type {Entry} */ (fileList.item(i)), value)) {
      this.fileListSelection_.leadIndex = i;
      return;
    }
  }
};

/**
 * Schedule rescan with short delay.
 * @param {boolean} refresh True to refresh metadata, or false to use cached
 *     one.
 */
DirectoryModel.prototype.rescanSoon = function(refresh) {
  this.scheduleRescan(SHORT_RESCAN_INTERVAL, refresh);
};

/**
 * Schedule rescan with delay. Designed to handle directory change
 * notification.
 * @param {boolean} refresh True to refresh metadata, or false to use cached
 *     one.
 */
DirectoryModel.prototype.rescanLater = function(refresh) {
  this.scheduleRescan(SIMULTANEOUS_RESCAN_INTERVAL, refresh);
};

/**
 * Schedule rescan with delay. If another rescan has been scheduled does
 * nothing. File operation may cause a few notifications what should cause
 * a single refresh.
 * @param {number} delay Delay in ms after which the rescan will be performed.
 * @param {boolean} refresh True to refresh metadata, or false to use cached
 *     one.
 */
DirectoryModel.prototype.scheduleRescan = function(delay, refresh) {
  if (this.rescanTime_) {
    if (this.rescanTime_ <= Date.now() + delay) {
      return;
    }
    clearTimeout(this.rescanTimeoutId_);
  }

  var sequence = this.changeDirectorySequence_;

  this.rescanTime_ = Date.now() + delay;
  this.rescanTimeoutId_ = setTimeout(function() {
    this.rescanTimeoutId_ = null;
    if (sequence === this.changeDirectorySequence_) {
      this.rescan(refresh);
    }
  }.bind(this), delay);
};

/**
 * Cancel a rescan on timeout if it is scheduled.
 * @private
 */
DirectoryModel.prototype.clearRescanTimeout_ = function() {
  this.rescanTime_ = null;
  if (this.rescanTimeoutId_) {
    clearTimeout(this.rescanTimeoutId_);
    this.rescanTimeoutId_ = null;
  }
};

/**
 * Rescan current directory. May be called indirectly through rescanLater or
 * directly in order to reflect user action. Will first cache all the directory
 * contents in an array, then seamlessly substitute the fileList contents,
 * preserving the select element etc.
 *
 * This should be to scan the contents of current directory (or search).
 *
 * @param {boolean} refresh True to refresh metadata, or false to use cached
 *     one.
 */
DirectoryModel.prototype.rescan = function(refresh) {
  this.clearRescanTimeout_();
  if (this.runningScan_) {
    this.pendingRescan_ = true;
    return;
  }

  var dirContents = this.currentDirContents_.clone();
  dirContents.setFileList(new FileListModel(this.metadataModel_));
  dirContents.setMetadataSnapshot(
      this.currentDirContents_.createMetadataSnapshot());

  var sequence = this.changeDirectorySequence_;

  var successCallback = (function() {
    if (sequence === this.changeDirectorySequence_) {
      this.replaceDirectoryContents_(dirContents);
      cr.dispatchSimpleEvent(this, 'rescan-completed');
    }
  }).bind(this);

  this.scan_(dirContents,
             refresh,
             successCallback, function() {}, function() {}, function() {});
};

/**
 * Run scan on the current DirectoryContents. The active fileList is cleared and
 * the entries are added directly.
 *
 * This should be used when changing directory or initiating a new search.
 *
 * @param {DirectoryContents} newDirContents New DirectoryContents instance to
 *     replace currentDirContents_.
 * @param {function(boolean)} callback Callback with result. True if the scan
 *     is completed successfully, false if the scan is failed.
 * @private
 */
DirectoryModel.prototype.clearAndScan_ = function(newDirContents, callback) {
  if (this.currentDirContents_.isScanning()) {
    this.currentDirContents_.cancelScan();
  }
  this.currentDirContents_ = newDirContents;
  this.clearRescanTimeout_();

  if (this.pendingScan_) {
    this.pendingScan_ = false;
  }

  if (this.runningScan_) {
    if (this.runningScan_.isScanning()) {
      this.runningScan_.cancelScan();
    }
    this.runningScan_ = null;
  }

  var sequence = this.changeDirectorySequence_;
  var cancelled = false;

  var onDone = function() {
    if (cancelled) {
      return;
    }

    cr.dispatchSimpleEvent(this, 'scan-completed');
    callback(true);
  }.bind(this);

  /** @param {DOMError} error error. */
  var onFailed = function(error) {
    if (cancelled) {
      return;
    }

    var event = new Event('scan-failed');
    event.error = error;
    this.dispatchEvent(event);
    callback(false);
  }.bind(this);

  var onUpdated = function() {
    if (cancelled) {
      return;
    }

    if (this.changeDirectorySequence_ !== sequence) {
      cancelled = true;
      cr.dispatchSimpleEvent(this, 'scan-cancelled');
      callback(false);
      return;
    }

    cr.dispatchSimpleEvent(this, 'scan-updated');
  }.bind(this);

  var onCancelled = function() {
    if (cancelled) {
      return;
    }

    cancelled = true;
    cr.dispatchSimpleEvent(this, 'scan-cancelled');
    callback(false);
  }.bind(this);

  // Clear metadata information for the old (no longer visible) items in the
  // file list.
  var fileList = this.getFileList();
  let removedUrls = [];
  for (var i = 0; i < fileList.length; i++) {
    removedUrls.push(fileList.item(i).toURL());
  }
  this.metadataModel_.notifyEntriesRemoved(removedUrls);

  // Retrieve metadata information for the newly selected directory.
  const currentEntry = this.currentDirContents_.getDirectoryEntry();
  if (currentEntry && !util.isFakeEntry(assert(currentEntry))) {
    this.metadataModel_.get(
        [currentEntry],
        constants.LIST_CONTAINER_METADATA_PREFETCH_PROPERTY_NAMES);
  }

  // Clear the table, and start scanning.
  cr.dispatchSimpleEvent(this, 'scan-started');
  fileList.splice(0, fileList.length);
  this.scan_(this.currentDirContents_, false,
             onDone, onFailed, onUpdated, onCancelled);
};

/**
 * Adds/removes/updates items of file list.
 * @param {Array<Entry>} changedEntries Entries of updated/added files.
 * @param {Array<string>} removedUrls URLs of removed files.
 * @private
 */
DirectoryModel.prototype.partialUpdate_ =
    function(changedEntries, removedUrls) {
  // This update should be included in the current running update.
  if (this.pendingScan_) {
    return;
  }

  if (this.runningScan_) {
    // Do update after the current scan is finished.
    var previousScan = this.runningScan_;
    var onPreviousScanCompleted = function() {
      previousScan.removeEventListener('scan-completed',
                                       onPreviousScanCompleted);
      // Run the update asynchronously.
      Promise.resolve().then(function() {
        this.partialUpdate_(changedEntries, removedUrls);
      }.bind(this));
    }.bind(this);
    previousScan.addEventListener('scan-completed', onPreviousScanCompleted);
    return;
  }

  var onFinish = function() {
    this.runningScan_ = null;

    this.currentDirContents_.removeEventListener(
        'scan-completed', onCompleted);
    this.currentDirContents_.removeEventListener('scan-failed', onFailure);
    this.currentDirContents_.removeEventListener(
        'scan-cancelled', onCancelled);
  }.bind(this);

  var onCompleted = function() {
    onFinish();
    cr.dispatchSimpleEvent(this, 'rescan-completed');
  }.bind(this);

  var onFailure = function() {
    onFinish();
  };

  var onCancelled = function() {
    onFinish();
  };

  this.runningScan_ = this.currentDirContents_;
  this.currentDirContents_.addEventListener('scan-completed', onCompleted);
  this.currentDirContents_.addEventListener('scan-failed', onFailure);
  this.currentDirContents_.addEventListener('scan-cancelled', onCancelled);
  this.currentDirContents_.update(changedEntries, removedUrls);
};

/**
 * Perform a directory contents scan. Should be called only from rescan() and
 * clearAndScan_().
 *
 * @param {DirectoryContents} dirContents DirectoryContents instance on which
 *     the scan will be run.
 * @param {boolean} refresh True to refresh metadata, or false to use cached
 *     one.
 * @param {function()} successCallback Callback on success.
 * @param {function(DOMError)} failureCallback Callback on failure.
 * @param {function()} updatedCallback Callback on update. Only on the last
 *     update, {@code successCallback} is called instead of this.
 * @param {function()} cancelledCallback Callback on cancel.
 * @private
 */
DirectoryModel.prototype.scan_ = function(
    dirContents,
    refresh,
    successCallback, failureCallback, updatedCallback, cancelledCallback) {
  var self = this;

  /**
   * Runs pending scan if there is one.
   *
   * @return {boolean} Did pending scan exist.
   */
  var maybeRunPendingRescan = function() {
    if (this.pendingRescan_) {
      this.rescanSoon(refresh);
      this.pendingRescan_ = false;
      return true;
    }
    return false;
  }.bind(this);

  var onFinished = function() {
    dirContents.removeEventListener('scan-completed', onSuccess);
    dirContents.removeEventListener('scan-updated', updatedCallback);
    dirContents.removeEventListener('scan-failed', onFailure);
    dirContents.removeEventListener('scan-cancelled', cancelledCallback);
  };

  var onSuccess = function() {
    onFinished();

    // Record metric for Downloads directory.
    if (!dirContents.isSearch()) {
      var locationInfo =
          this.volumeManager_.getLocationInfo(
              assert(dirContents.getDirectoryEntry()));
      var volumeInfo = locationInfo && locationInfo.volumeInfo;
      if (volumeInfo &&
          volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS &&
          locationInfo.isRootEntry) {
        metrics.recordMediumCount(
            'DownloadsCount', dirContents.getFileListLength());
      }
    }

    this.runningScan_ = null;
    successCallback();
    this.scanFailures_ = 0;
    maybeRunPendingRescan();
  }.bind(this);

  var onFailure = function(event) {
    onFinished();

    this.runningScan_ = null;
    this.scanFailures_++;
    failureCallback(event.error);

    if (maybeRunPendingRescan()) {
      return;
    }

    // Do not rescan for crostini errors.
    if (event.error.name === DirectoryModel.CROSTINI_CONNECT_ERR) {
      return;
    }

    if (this.scanFailures_ <= 1) {
      this.rescanLater(refresh);
    }
  }.bind(this);

  var onCancelled = function() {
    onFinished();
    cancelledCallback();
  };

  this.runningScan_ = dirContents;

  dirContents.addEventListener('scan-completed', onSuccess);
  dirContents.addEventListener('scan-updated', updatedCallback);
  dirContents.addEventListener('scan-failed', onFailure);
  dirContents.addEventListener('scan-cancelled', onCancelled);
  dirContents.scan(refresh);
};

/**
 * @param {DirectoryContents} dirContents DirectoryContents instance. This must
 *     be a different instance from this.currentDirContents_.
 * @private
 */
DirectoryModel.prototype.replaceDirectoryContents_ = function(dirContents) {
  console.assert(this.currentDirContents_ !== dirContents,
      'Give directory contents instance must be different from current one.');
  cr.dispatchSimpleEvent(this, 'begin-update-files');
  this.updateSelectionAndPublishEvent_(this.fileListSelection_, function() {
    var selectedEntries = this.getSelectedEntries_();
    var selectedIndices = this.fileListSelection_.selectedIndexes;

    // Restore leadIndex in case leadName no longer exists.
    var leadIndex = this.fileListSelection_.leadIndex;
    var leadEntry = this.getLeadEntry_();
    const isCheckSelectMode = this.fileListSelection_.getCheckSelectMode();

    var previousDirContents = this.currentDirContents_;
    this.currentDirContents_ = dirContents;
    this.currentDirContents_.replaceContextFileList();

    this.setSelectedEntries_(selectedEntries);
    this.fileListSelection_.leadIndex = leadIndex;
    this.setLeadEntry_(leadEntry);

    // If nothing is selected after update, then select file next to the
    // latest selection
    var forceChangeEvent = false;
    if (this.fileListSelection_.selectedIndexes.length == 0 &&
        selectedIndices.length != 0) {
      var maxIdx = Math.max.apply(null, selectedIndices);
      this.selectIndex(Math.min(maxIdx - selectedIndices.length + 2,
                                this.getFileList().length) - 1);
      forceChangeEvent = true;
    } else if (isCheckSelectMode) {
      // Otherwise, ensure check select mode is retained if it was previously
      // active.
      this.fileListSelection_.setCheckSelectMode(true);
    }
    return forceChangeEvent;
  }.bind(this));

  cr.dispatchSimpleEvent(this, 'end-update-files');
};

/**
 * Callback when an entry is changed.
 * @param {EntriesChangedEvent} event Entry change event.
 * @private
 */
DirectoryModel.prototype.onEntriesChanged_ = function(event) {
  var kind = event.kind;
  var entries = event.entries;
  // TODO(hidehiko): We should update directory model even the search result
  // is shown.
  var rootType = this.getCurrentRootType();
  if ((rootType === VolumeManagerCommon.RootType.DRIVE ||
       rootType === VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME ||
       rootType === VolumeManagerCommon.RootType.DRIVE_RECENT ||
       rootType === VolumeManagerCommon.RootType.DRIVE_OFFLINE) &&
      this.isSearching()) {
    return;
  }

  switch (kind) {
    case util.EntryChangedKind.CREATED:
      var parentPromises = [];
      for (var i = 0; i < entries.length; i++) {
        parentPromises.push(new Promise(function(resolve, reject) {
          entries[i].getParent(resolve, reject);
        }));
      }
      Promise.all(parentPromises).then(function(parents) {
        var entriesToAdd = [];
        for (var i = 0; i < parents.length; i++) {
          if (!util.isSameEntry(parents[i], this.getCurrentDirEntry())) {
            continue;
          }
          var index = this.findIndexByEntry_(entries[i]);
          if (index >= 0) {
            this.getFileList().replaceItem(
                this.getFileList().item(index), entries[i]);
          } else {
            entriesToAdd.push(entries[i]);
          }
        }
        this.partialUpdate_(entriesToAdd, []);
      }.bind(this)).catch(function(error) {
        console.error(error.stack || error);
      });
      break;

    case util.EntryChangedKind.DELETED:
      // This is the delete event.
      this.partialUpdate_([], util.entriesToURLs(entries));
      break;

    default:
      console.error('Invalid EntryChangedKind: ' + kind);
      break;
  }
};

/**
 * @param {Entry} entry The entry to be searched.
 * @return {number} The index in the fileList, or -1 if not found.
 * @private
 */
DirectoryModel.prototype.findIndexByEntry_ = function(entry) {
  var fileList = this.getFileList();
  for (var i = 0; i < fileList.length; i++) {
    if (util.isSameEntry(/** @type {Entry} */ (fileList.item(i)), entry)) {
      return i;
    }
  }
  return -1;
};

/**
 * Called when rename is done successfully.
 * Note: conceptually, DirectoryModel should work without this, because entries
 * can be renamed by other systems anytime and the Files app should reflect it
 * correctly.
 * TODO(hidehiko): investigate more background, and remove this if possible.
 *
 * @param {!Entry} oldEntry The old entry.
 * @param {!Entry} newEntry The new entry.
 * @param {function()=} opt_callback Called on completion.
 */
DirectoryModel.prototype.onRenameEntry = function(
    oldEntry, newEntry, opt_callback) {
  this.currentDirContents_.prefetchMetadata([newEntry], true, function() {
    // If the current directory is the old entry, then quietly change to the
    // new one.
    if (util.isSameEntry(oldEntry, this.getCurrentDirEntry())) {
      this.changeDirectoryEntry(
          /** @type {!DirectoryEntry|!FilesAppDirEntry} */ (newEntry));
    }

    // Replace the old item with the new item. oldEntry instance itself may
    // have been removed/replaced from the list during the async process, we
    // find an entry which should be replaced by checking toURL().
    var list = this.getFileList();
    var oldEntryExist = false;
    var newEntryExist = false;
    var oldEntryUrl = oldEntry.toURL();
    var newEntryUrl = newEntry.toURL();

    for (var i = 0; i < list.length; i++) {
      var item = list.item(i);
      var url = item.toURL();
      if (url === oldEntryUrl) {
        list.replaceItem(item, newEntry);
        oldEntryExist = true;
        break;
      }

      if (url === newEntryUrl) {
        newEntryExist = true;
      }
    }

    // When both old and new entries don't exist, it may be in the middle of
    // update process. In DirectoryContent.update deletion is executed at first
    // and insertion is executed as a async call. There is a chance that this
    // method is called in the middle of update process.
    if (!oldEntryExist && !newEntryExist) {
      list.push(newEntry);
    }

    // Run callback, finally.
    if (opt_callback) {
      opt_callback();
    }
  }.bind(this));
};

/**
 * Updates data model and selects new directory.
 * @param {!DirectoryEntry} newDirectory Directory entry to be selected.
 * @return {Promise} A promise which is resolved when new directory is selected.
 *     If current directory has changed during the operation, this will be
 *     rejected.
 */
DirectoryModel.prototype.updateAndSelectNewDirectory = function(newDirectory) {
  // Refresh the cache.
  this.metadataModel_.notifyEntriesCreated([newDirectory]);
  var dirContents = this.currentDirContents_;

  return new Promise(function(onFulfilled, onRejected) {
    dirContents.prefetchMetadata(
        [newDirectory], false, onFulfilled);
  }).then(function(sequence) {
    // If current directory has changed during the prefetch, do not try to
    // select new directory.
    if (sequence !== this.changeDirectorySequence_) {
      return Promise.reject();
    }

    // If target directory is already in the list, just select it.
    var existing = this.getFileList().slice().filter(function(e) {
      return e.name === newDirectory.name;
    });
    if (existing.length) {
      this.selectEntry(newDirectory);
    } else {
      this.fileListSelection_.beginChange();
      this.getFileList().splice(0, 0, newDirectory);
      this.selectEntry(newDirectory);
      this.fileListSelection_.endChange();
    }
  }.bind(this, this.changeDirectorySequence_));
};

/**
 * Sets the current MyFilesEntry.
 * @param {FilesAppDirEntry} myFilesEntry
 */
DirectoryModel.prototype.setMyFiles = function(myFilesEntry) {
  this.myFilesEntry_ = myFilesEntry;
};

/**
 * Changes the current directory to the directory represented by
 * a DirectoryEntry or a fake entry.
 *
 * Dispatches the 'directory-changed' event when the directory is successfully
 * changed.
 *
 * Note : if this is called from UI, please consider to use DirectoryModel.
 * activateDirectoryEntry instead of this, which is higher-level function and
 * cares about the selection.
 *
 * @param {!DirectoryEntry|!FilesAppDirEntry} dirEntry The entry of the new
 *     directory to be opened.
 * @param {function()=} opt_callback Executed if the directory loads
 *     successfully.
 */
DirectoryModel.prototype.changeDirectoryEntry = function(
    dirEntry, opt_callback) {
  // Increment the sequence value.
  this.changeDirectorySequence_++;
  this.clearSearch_();

  // When switching to MyFiles volume, we should use a FilesAppEntry if
  // available because it returns UI-only entries too, like Linux files and Play
  // files.
  const locationInfo = this.volumeManager_.getLocationInfo(dirEntry);
  if (util.isMyFilesVolumeEnabled() && locationInfo && this.myFilesEntry_ &&
      locationInfo.rootType === VolumeManagerCommon.RootType.DOWNLOADS &&
      locationInfo.isRootEntry) {
    dirEntry = this.myFilesEntry_;
  }

  // If there is on-going scan, cancel it.
  if (this.currentDirContents_.isScanning()) {
    this.currentDirContents_.cancelScan();
  }

  this.directoryChangeQueue_.run(function(sequence, queueTaskCallback) {
    this.fileWatcher_.changeWatchedDirectory(dirEntry)
        .then(function() {
          if (this.changeDirectorySequence_ !== sequence) {
            queueTaskCallback();
            return;
          }

          var newDirectoryContents = this.createDirectoryContents_(
              this.currentFileListContext_, dirEntry, '');
          if (!newDirectoryContents) {
            queueTaskCallback();
            return;
          }

          var previousDirEntry =
              this.currentDirContents_.getDirectoryEntry();
          this.clearAndScan_(
               newDirectoryContents,
               function(result) {
                 // Calls the callback of the method when successful.
                 if (result && opt_callback) {
                   opt_callback();
                 }

                 // Notify that the current task of this.directoryChangeQueue_
                 // is completed.
                 setTimeout(queueTaskCallback, 0);
               });

          // For tests that open the dialog to empty directories, everything
          // is loaded at this point.
          util.testSendMessage('directory-change-complete');
          var previousVolumeInfo =
              previousDirEntry ?
              this.volumeManager_.getVolumeInfo(previousDirEntry) : null;
          // VolumeInfo for dirEntry.
          var currentVolumeInfo = this.getCurrentVolumeInfo();
          var event = new Event('directory-changed');
          event.previousDirEntry = previousDirEntry;
          event.newDirEntry = dirEntry;
          event.volumeChanged = previousVolumeInfo !== currentVolumeInfo;
          this.dispatchEvent(event);
        }.bind(this));
  }.bind(this, this.changeDirectorySequence_));
};

/**
 * Activates the given directory.
 * This method:
 *  - Changes the current directory, if the given directory is not the current
 *    directory.
 *  - Clears the selection, if the given directory is the current directory.
 *
 * @param {!DirectoryEntry|!FilesAppDirEntry} dirEntry The entry of the new
 *     directory to be opened.
 * @param {function()=} opt_callback Executed if the directory loads
 *     successfully.
 */
DirectoryModel.prototype.activateDirectoryEntry = function(
    dirEntry, opt_callback) {
  var currentDirectoryEntry = this.getCurrentDirEntry();
  if (currentDirectoryEntry &&
      util.isSameEntry(dirEntry, currentDirectoryEntry)) {
    // On activating the current directory, clear the selection on the filelist.
    this.clearSelection();
  } else {
    // Otherwise, changes the current directory.
    this.changeDirectoryEntry(dirEntry, opt_callback);
  }
};

/**
 * Clears the selection in the file list.
 */
DirectoryModel.prototype.clearSelection = function() {
  this.setSelectedEntries_([]);
};

/**
 * Creates an object which could say whether directory has changed while it has
 * been active or not. Designed for long operations that should be cancelled
 * if the used change current directory.
 * @return {Object} Created object.
 */
DirectoryModel.prototype.createDirectoryChangeTracker = function() {
  var tracker = {
    dm_: this,
    active_: false,
    hasChanged: false,

    start: function() {
      if (!this.active_) {
        this.dm_.addEventListener('directory-changed',
                                  this.onDirectoryChange_);
        this.active_ = true;
        this.hasChanged = false;
      }
    },

    stop: function() {
      if (this.active_) {
        this.dm_.removeEventListener('directory-changed',
                                     this.onDirectoryChange_);
        this.active_ = false;
      }
    },

    onDirectoryChange_: function(event) {
      tracker.stop();
      tracker.hasChanged = true;
    }
  };
  return tracker;
};

/**
 * @param {Entry} entry Entry to be selected.
 */
DirectoryModel.prototype.selectEntry = function(entry) {
  var fileList = this.getFileList();
  for (var i = 0; i < fileList.length; i++) {
    if (fileList.item(i).toURL() === entry.toURL()) {
      this.selectIndex(i);
      return;
    }
  }
};

/**
 * @param {Array<Entry>} entries Array of entries.
 */
DirectoryModel.prototype.selectEntries = function(entries) {
  // URLs are needed here, since we are comparing Entries by URLs.
  var urls = util.entriesToURLs(entries);
  var fileList = this.getFileList();
  this.fileListSelection_.beginChange();
  this.fileListSelection_.unselectAll();
  for (var i = 0; i < fileList.length; i++) {
    if (urls.indexOf(fileList.item(i).toURL()) >= 0) {
      this.fileListSelection_.setIndexSelected(i, true);
    }
  }
  this.fileListSelection_.endChange();
};

/**
 * @param {number} index Index of file.
 */
DirectoryModel.prototype.selectIndex = function(index) {
  // this.focusCurrentList_();
  if (index >= this.getFileList().length) {
    return;
  }

  // If a list bound with the model it will do scrollIndexIntoView(index).
  this.fileListSelection_.selectedIndex = index;
};

/**
 * Handles update of VolumeInfoList.
 * @param {Event} event Event of VolumeInfoList's 'splice'.
 * @private
 */
DirectoryModel.prototype.onVolumeInfoListUpdated_ = function(event) {
  // Fallback to the default volume's root if the current volume is unmounted.
  if (this.hasCurrentDirEntryBeenUnmounted_(event.removed)) {
    this.volumeManager_.getDefaultDisplayRoot((displayRoot) => {
      if (displayRoot) {
        this.changeDirectoryEntry(displayRoot);
      }
    });
  }

  // If a volume within My files is mounted, rescan the contents.
  // TODO(crbug.com/901690): Remove this special case.
  if (this.getCurrentRootType() === VolumeManagerCommon.RootType.MY_FILES) {
    for (let newVolume of event.added) {
      if (newVolume.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS ||
          newVolume.volumeType ===
              VolumeManagerCommon.VolumeType.ANDROID_FILES ||
          newVolume.volumeType === VolumeManagerCommon.VolumeType.CROSTINI) {
        this.rescan(false);
        break;
      }
    }
  }

  // If the current directory is the Drive placeholder and the real Drive is
  // mounted, switch to it.
  if (this.getCurrentRootType() ===
      VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT) {
    for (let newVolume of event.added) {
      if (newVolume.volumeType === VolumeManagerCommon.VolumeType.DRIVE) {
        newVolume.resolveDisplayRoot().then((displayRoot) => {
          this.changeDirectoryEntry(displayRoot);
        });
      }
    }
  }
  // If a new file backed provided volume is mounted,
  // then redirect to it in the focused window.
  // If crostini is mounted, redirect even if window is not focused.
  // Note, that this is a temporary solution for https://crbug.com/427776.
  if (event.added.length !== 1) {
    return;
  }
  if ((window.isFocused() &&
       event.added[0].volumeType === VolumeManagerCommon.VolumeType.PROVIDED &&
       event.added[0].source === VolumeManagerCommon.Source.FILE) ||
      event.added[0].volumeType === VolumeManagerCommon.VolumeType.CROSTINI) {
    event.added[0].resolveDisplayRoot().then((displayRoot) => {
      // Resolving a display root on FSP volumes is instant, despite the
      // asynchronous call.
      this.changeDirectoryEntry(event.added[0].displayRoot);
    });
  }
};

/**
 * Returns whether the current directory entry has been unmounted.
 *
 * @param {!Array<!VolumeInfo>} removedVolumes The removed volumes.
 * @private
 */
DirectoryModel.prototype.hasCurrentDirEntryBeenUnmounted_ = function(
    removedVolumes) {
  const entry = this.getCurrentDirEntry();
  if (!entry) {
    return false;
  }

  if (!util.isFakeEntry(entry)) {
    return !this.volumeManager_.getVolumeInfo(entry);
  }

  const rootType = this.getCurrentRootType();
  for (let volume of removedVolumes) {
    if (volume.fakeEntries[rootType]) {
      return true;
    }
    // The removable root is selected and one of its child partitions has been
    // unmounted.
    if (volume.prefixEntry === entry) {
      return true;
    }
  }
  return false;
};

/**
 * Creates directory contents for the entry and query.
 *
 * @param {FileListContext} context File list context.
 * @param {!DirectoryEntry|!FilesAppEntry} entry Current directory.
 * @param {string=} opt_query Search query string.
 * @return {DirectoryContents} Directory contents.
 * @private
 */
DirectoryModel.prototype.createDirectoryContents_ =
    function(context, entry, opt_query) {
  var query = (opt_query || '').trimLeft();
  var locationInfo = this.volumeManager_.getLocationInfo(entry);
  var canUseDriveSearch = this.volumeManager_.getDriveConnectionState().type !==
          VolumeManagerCommon.DriveConnectionType.OFFLINE &&
      (locationInfo && locationInfo.isDriveBased);

  if (entry.rootType == VolumeManagerCommon.RootType.RECENT) {
    return DirectoryContents.createForRecent(
        context, /** @type {!FakeEntry} */ (entry), query);
  }
  if (entry.rootType == VolumeManagerCommon.RootType.CROSTINI) {
    return DirectoryContents.createForCrostiniMounter(
        context, /** @type {!FakeEntry} */ (entry));
  }
  if (entry.rootType == VolumeManagerCommon.RootType.MY_FILES) {
    return DirectoryContents.createForDirectory(
        context, /** @type {!FilesAppDirEntry} */ (entry));
  }
  if (entry.rootType == VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT) {
    return DirectoryContents.createForFakeDrive(
        context, /** @type {!FakeEntry} */ (entry));
  }
  if (query && canUseDriveSearch) {
    // Drive search.
    return DirectoryContents.createForDriveSearch(
        context, /** @type {!DirectoryEntry} */ (entry), query);
  }
  if (query) {
    // Local search.
    return DirectoryContents.createForLocalSearch(
        context, /** @type {!DirectoryEntry} */ (entry), query);
  }

  if (!locationInfo) {
    return null;
  }

  if (locationInfo.rootType == VolumeManagerCommon.RootType.MEDIA_VIEW) {
    return DirectoryContents.createForMediaView(
        context, /** @type {!DirectoryEntry} */ (entry));
  }

  if (locationInfo.isSpecialSearchRoot) {
    // Drive special search.
    var searchType;
    switch (locationInfo.rootType) {
      case VolumeManagerCommon.RootType.DRIVE_OFFLINE:
        searchType =
            DriveMetadataSearchContentScanner.SearchType.SEARCH_OFFLINE;
        break;
      case VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME:
        searchType =
            DriveMetadataSearchContentScanner.SearchType.SEARCH_SHARED_WITH_ME;
        break;
      case VolumeManagerCommon.RootType.DRIVE_RECENT:
        searchType =
            DriveMetadataSearchContentScanner.SearchType.SEARCH_RECENT_FILES;
        break;
      default:
        // Unknown special search entry.
        throw new Error('Unknown special search type.');
    }
    return DirectoryContents.createForDriveMetadataSearch(
        context,
        /** @type {!FakeEntry} */ (entry),
        searchType);
  }
  // Local fetch or search.
  return DirectoryContents.createForDirectory(
      context, /** @type {!DirectoryEntry} */ (entry));
};

/**
 * Gets the last search query.
 * @return {string} the last search query.
 */
DirectoryModel.prototype.getLastSearchQuery = function() {
  return this.lastSearchQuery_;
};

/**
 * Clears the last search query with the empty string.
 */
DirectoryModel.prototype.clearLastSearchQuery = function() {
  this.lastSearchQuery_ = '';
};

/**
 * Performs search and displays results. The search type is dependent on the
 * current directory. If we are currently on drive, server side content search
 * over drive mount point. If the current directory is not on the drive, file
 * name search over current directory will be performed.
 *
 * @param {string} query Query that will be searched for.
 * @param {function(Event)} onSearchRescan Function that will be called when the
 *     search directory is rescanned (i.e. search results are displayed).
 * @param {function()} onClearSearch Function to be called when search state
 *     gets cleared.
 * TODO(olege): Change callbacks to events.
 */
DirectoryModel.prototype.search = function(query,
                                           onSearchRescan,
                                           onClearSearch) {
  this.lastSearchQuery_ = query;
  this.clearSearch_();
  var currentDirEntry = this.getCurrentDirEntry();
  if (!currentDirEntry) {
    // Not yet initialized. Do nothing.
    return;
  }

  this.changeDirectorySequence_++;
  this.directoryChangeQueue_.run(function(sequence, callback) {
    if (this.changeDirectorySequence_ !== sequence) {
      callback();
      return;
    }

    if (!(query || '').trimLeft()) {
      if (this.isSearching()) {
        var newDirContents = this.createDirectoryContents_(
            this.currentFileListContext_,
            assert(currentDirEntry));
        this.clearAndScan_(newDirContents,
                           callback);
      } else {
        callback();
      }
      return;
    }

    var newDirContents = this.createDirectoryContents_(
        this.currentFileListContext_, assert(currentDirEntry), query);
    if (!newDirContents) {
      callback();
      return;
    }

    this.onSearchCompleted_ = onSearchRescan;
    this.onClearSearch_ = onClearSearch;
    this.addEventListener('scan-completed', this.onSearchCompleted_);
    this.clearAndScan_(newDirContents,
                       callback);
  }.bind(this, this.changeDirectorySequence_));
};

/**
 * In case the search was active, remove listeners and send notifications on
 * its canceling.
 * @private
 */
DirectoryModel.prototype.clearSearch_ = function() {
  if (!this.isSearching()) {
    return;
  }

  if (this.onSearchCompleted_) {
    this.removeEventListener('scan-completed', this.onSearchCompleted_);
    this.onSearchCompleted_ = null;
  }

  if (this.onClearSearch_) {
    this.onClearSearch_();
    this.onClearSearch_ = null;
  }
};

/**
 * DOMError type for crostini connection failure.
 * @const {string}
 */
DirectoryModel.CROSTINI_CONNECT_ERR = 'CrostiniConnectErr';
