// 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.

'use strict';

/**
 * Map of all currently open app window. The key is an app id.
 */
var appWindows = {};

/**
 * Synchronous queue for asynchronous calls.
 * @type {AsyncUtil.Queue}
 */
var queue = new AsyncUtil.Queue();

/**
 * @return {Array.<DOMWindow>} Array of content windows for all currently open
 *   app windows.
 */
function getContentWindows() {
  var views = [];
  for (var key in appWindows) {
    if (appWindows.hasOwnProperty(key))
      views.push(appWindows[key].contentWindow);
  }
  return views;
}

/**
 * Type of a Files.app's instance launch.
 * @enum {number}
 */
var LaunchType = {
  ALWAYS_CREATE: 0,
  FOCUS_ANY_OR_CREATE: 1,
  FOCUS_SAME_OR_CREATE: 2
};

/**
 * Wrapper for an app window.
 *
 * Expects the following from the app scripts:
 * 1. The page load handler should initialize the app using |window.appState|
 *    and call |util.platform.saveAppState|.
 * 2. Every time the app state changes the app should update |window.appState|
 *    and call |util.platform.saveAppState| .
 * 3. The app may have |unload| function to persist the app state that does not
 *    fit into |window.appState|.
 *
 * @param {AsyncUtil.Queue} queue Queue for asynchronous window launches.
 * @param {string} url App window content url.
 * @param {string} id App window id.
 * @param {Object|function()} options Options object or a function to create it.
 * @constructor
 */
function AppWindowWrapper(queue, url, id, options) {
  this.queue_ = queue;
  this.url_ = url;
  this.id_ = id;
  this.options_ = options;
  this.window_ = null;
}

/**
 * Shift distance to avoid overlapping windows.
 * @type {number}
 * @const
 */
AppWindowWrapper.SHIFT_DISTANCE = 40;

/**
 * @return {boolean} True if the window is currently open.
 */
AppWindowWrapper.prototype.isOpen = function() {
  return this.window_ && !this.window_.contentWindow.closed;
};

/**
 * Gets similar windows, it means with the same initial url.
 * @return {Array.<AppWindow>} List of similar windows.
 * @private
 */
AppWindowWrapper.prototype.getSimilarWindows_ = function() {
  var result = [];
  for (var appID in appWindows) {
    if (appWindows[appID].contentWindow.appInitialURL == this.url_)
      result.push(appWindows[appID]);
  }
  return result;
};

/**
 * Opens the window.
 *
 * @param {Object} appState App state.
 * @param {function()} callback Completion callback.
 */
AppWindowWrapper.prototype.launch = function(appState, callback) {
  if (this.isOpen()) {
    console.error('The window is already open');
    callback();
    return;
  }
  this.appState_ = appState;

  var options = this.options_;
  if (typeof options == 'function')
    options = options();
  options.id = this.url_;  // This is to make Chrome reuse window geometries.
  options.singleton = false;
  options.hidden = true;

  // Get similar windows, it means with the same initial url, eg. different
  // main windows of Files.app.
  var similarWindows = this.getSimilarWindows_();

  // Closure creating the window, once all preprocessing tasks are finished.
  var createWindow = function() {
    chrome.app.window.onRestored.removeListener(createWindow);
    chrome.app.window.create(this.url_, options, function(appWindow) {
      this.window_ = appWindow;

      // If we have already another window of the same kind, then shift this
      // window to avoid overlapping with the previous one.
      if (similarWindows.length) {
        var bounds = appWindow.getBounds();
        appWindow.moveTo(bounds.left + AppWindowWrapper.SHIFT_DISTANCE,
                         bounds.top + AppWindowWrapper.SHIFT_DISTANCE);
      }

      // Show after changing bounds is done. For the new UI, Files.app shows
      // it's window as soon as the UI is pre-initialized.
      if (!this.id_.match(FILES_ID_PATTERN))
        appWindow.show();

      appWindows[this.id_] = appWindow;
      var contentWindow = appWindow.contentWindow;
      contentWindow.appID = this.id_;
      contentWindow.appState = this.appState_;
      contentWindow.appInitialURL = this.url_;
      appWindow.onClosed.addListener(function() {
        if (contentWindow.unload)
          contentWindow.unload();
        if (contentWindow.saveOnExit) {
          contentWindow.saveOnExit.forEach(function(entry) {
            util.AppCache.update(entry.key, entry.value);
          });
        }
        delete appWindows[this.id_];
        chrome.storage.local.remove(this.id_);  // Forget the persisted state.
        this.window_ = null;
        maybeCloseBackgroundPage();
      }.bind(this));

      callback();
    }.bind(this));
  }.bind(this);

  // Restore maximized windows, to avoid hiding them to tray, which can be
  // confusing for users.
  for (var index = 0; index < similarWindows.length; index++) {
    if (similarWindows[index].isMaximized()) {
      var createWindowAndRemoveListener = function() {
        createWindow();
        similarWindows[index].onRestored.removeListener(
            createWindowAndRemoveListener);
      };
      similarWindows[index].onRestored.addListener(
          createWindowAndRemoveListener);
      similarWindows[index].restore();
      return;
    }
  }

  // If no maximized windows, then create the window immediately.
  createWindow();
};

/**
 * Enqueues opening the window.
 * @param {Object} appState App state.
 */
AppWindowWrapper.prototype.enqueueLaunch = function(appState) {
  this.queue_.run(this.launch.bind(this, appState));
};

/**
 * Wrapper for a singleton app window.
 *
 * In addition to the AppWindowWrapper requirements the app scripts should
 * have |reload| method that re-initializes the app based on a changed
 * |window.appState|.
 *
 * @param {AsyncUtil.Queue} queue Queue for asynchronous window launches.
 * @param {string} url App window content url.
 * @param {Object|function()} options Options object or a function to return it.
 * @constructor
 */
function SingletonAppWindowWrapper(queue, url, options) {
  AppWindowWrapper.call(this, queue, url, url, options);
}

/**
 * Inherits from AppWindowWrapper.
 */
SingletonAppWindowWrapper.prototype = { __proto__: AppWindowWrapper.prototype };

/**
 * Open the window.
 *
 * Activates an existing window or creates a new one.
 *
 * @param {Object} appState App state.
 * @param {function()} callback Completion callback.
 */
SingletonAppWindowWrapper.prototype.launch = function(appState, callback) {
  if (this.isOpen()) {
    this.window_.contentWindow.appState = appState;
    this.window_.contentWindow.reload();
    this.window_.focus();
    callback();
    return;
  }

  AppWindowWrapper.prototype.launch.call(this, appState, callback);
};

/**
 * Reopen a window if its state is saved in the local storage.
 */
SingletonAppWindowWrapper.prototype.reopen = function() {
  chrome.storage.local.get(this.id_, function(items) {
    var value = items[this.id_];
    if (!value)
      return;  // No app state persisted.

    try {
      var appState = JSON.parse(value);
    } catch (e) {
      console.error('Corrupt launch data for ' + this.id_, value);
      return;
    }
    this.enqueueLaunch(appState);
  }.bind(this));
};


/**
 * Prefix for the file manager window ID.
 */
var FILES_ID_PREFIX = 'files#';

/**
 * Regexp matching a file manager window ID.
 */
var FILES_ID_PATTERN = new RegExp('^' + FILES_ID_PREFIX + '(\\d*)$');

/**
 * Value of the next file manager window ID.
 */
var nextFileManagerWindowID = 0;

/**
 * @return {Object} File manager window create options.
 */
function createFileManagerOptions() {
  return {
    defaultLeft: Math.round(window.screen.availWidth * 0.1),
    defaultTop: Math.round(window.screen.availHeight * 0.1),
    defaultWidth: Math.round(window.screen.availWidth * 0.8),
    defaultHeight: Math.round(window.screen.availHeight * 0.8),
    minWidth: 320,
    minHeight: 240,
    frame: 'none',
    transparentBackground: true
  };
}

/**
 * @param {Object=} opt_appState App state.
 * @param {number=} opt_id Window id.
 * @param {LaunchType=} opt_type Launch type. Default: ALWAYS_CREATE.
 * @param {function(string)=} opt_callback Completion callback with the App ID.
 */
function launchFileManager(opt_appState, opt_id, opt_type, opt_callback) {
  var type = opt_type || LaunchType.ALWAYS_CREATE;

  // Wait until all windows are created.
  queue.run(function(onTaskCompleted) {
    // Check if there is already a window with the same path. If so, then
    // reuse it instead of opening a new one.
    if (type == LaunchType.FOCUS_SAME_OR_CREATE ||
        type == LaunchType.FOCUS_ANY_OR_CREATE) {
      if (opt_appState && opt_appState.defaultPath) {
        for (var key in appWindows) {
          var contentWindow = appWindows[key].contentWindow;
          if (contentWindow.appState &&
              opt_appState.defaultPath == contentWindow.appState.defaultPath) {
            appWindows[key].focus();
            if (opt_callback)
              opt_callback(key);
            onTaskCompleted();
            return;
          }
        }
      }
    }

    // Focus any window if none is focused. Try restored first.
    if (type == LaunchType.FOCUS_ANY_OR_CREATE) {
      // If there is already a focused window, then finish.
      for (var key in appWindows) {
        // The isFocused() method should always be available, but in case
        // Files.app's failed on some error, wrap it with try catch.
        try {
          if (appWindows[key].contentWindow.isFocused()) {
            if (opt_callback)
              opt_callback(key);
            onTaskCompleted();
            return;
          }
        } catch (e) {
          console.error(e.message);
        }
      }
      // Try to focus the first non-minimized window.
      for (var key in appWindows) {
        if (!appWindows[key].isMinimized()) {
          appWindows[key].focus();
          if (opt_callback)
            opt_callback(key);
          onTaskCompleted();
          return;
        }
      }
      // Restore and focus any window.
      for (var key in appWindows) {
        appWindows[key].focus();
        if (opt_callback)
          opt_callback(key);
        onTaskCompleted();
        return;
      }
    }

    // Create a new instance in case of ALWAYS_CREATE type, or as a fallback
    // for other types.

    var id = opt_id || nextFileManagerWindowID;
    nextFileManagerWindowID = Math.max(nextFileManagerWindowID, id + 1);
    var appId = FILES_ID_PREFIX + id;

    var appWindow = new AppWindowWrapper(
        queue,
        'main.html',
        appId,
        createFileManagerOptions);
    appWindow.enqueueLaunch(opt_appState || {});
    if (opt_callback)
      opt_callback(appId);
    onTaskCompleted();
  });
}

/**
 * Relaunch file manager windows based on the persisted state.
 */
function reopenFileManagers() {
  chrome.storage.local.get(function(items) {
    for (var key in items) {
      if (items.hasOwnProperty(key)) {
        var match = key.match(FILES_ID_PATTERN);
        if (match) {
          var id = Number(match[1]);
          try {
            var appState = JSON.parse(items[key]);
            launchFileManager(appState, id);
          } catch (e) {
            console.error('Corrupt launch data for ' + id);
          }
        }
      }
    }
  });
}

/**
 * Executes a file browser task.
 *
 * @param {string} action Task id.
 * @param {Object} details Details object.
 */
function onExecute(action, details) {
  var urls = details.entries.map(function(e) { return e.toURL() });

  switch (action) {
    case 'play':
      launchAudioPlayer({items: urls, position: 0});
      break;

    case 'watch':
      launchVideoPlayer(urls[0]);
      break;

    default:
      // Every other action opens a Files app window.
      var appState = {
        params: {
          action: action
        },
        defaultPath: details.entries[0].fullPath,
      };
      // For mounted devices just focus any Files.app window. The mounted
      // volume will appear on the volume list.
      var type = action == 'auto-open' ? LaunchType.FOCUS_ANY_OR_CREATE :
          LaunchType.FOCUS_SAME_OR_CREATE;
      launchFileManager(appState,
                        undefined,  // App ID.
                        type);
      break;
  }
}


/**
 * @return {Object} Audio player window create options.
 */
function createAudioPlayerOptions() {
  var WIDTH = 280;
  var MIN_HEIGHT = 35 + 58;
  var MAX_HEIGHT = 35 + 58 * 3;
  var BOTTOM = 80;
  var RIGHT = 20;

  return {
    defaultLeft: (window.screen.availWidth - WIDTH - RIGHT),
    defaultTop: (window.screen.availHeight - MIN_HEIGHT - BOTTOM),
    minHeight: MIN_HEIGHT,
    maxHeight: MAX_HEIGHT,
    height: MIN_HEIGHT,
    minWidth: WIDTH,
    maxWidth: WIDTH,
    width: WIDTH
  };
}

var audioPlayer = new SingletonAppWindowWrapper(queue,
                                                'mediaplayer.html',
                                                createAudioPlayerOptions);

/**
 * Launch the audio player.
 * @param {Object} playlist Playlist.
 */
function launchAudioPlayer(playlist) {
  audioPlayer.enqueueLaunch(playlist);
}

var videoPlayer = new SingletonAppWindowWrapper(queue,
                                                'video_player.html',
                                                {hidden: true});

/**
 * Launch the video player.
 * @param {string} url Video url.
 */
function launchVideoPlayer(url) {
  videoPlayer.enqueueLaunch({url: url});
}

/**
 * Launches the app.
 */
function onLaunched() {
  if (nextFileManagerWindowID == 0) {
    // The app just launched. Remove window state records that are not needed
    // any more.
    chrome.storage.local.get(function(items) {
      for (var key in items) {
        if (items.hasOwnProperty(key)) {
          if (key.match(FILES_ID_PATTERN))
            chrome.storage.local.remove(key);
        }
      }
    });
  }

  launchFileManager();
}

/**
 * Restarted the app, restore windows.
 */
function onRestarted() {
  reopenFileManagers();
  audioPlayer.reopen();
  videoPlayer.reopen();
}

/**
 * Handles clicks on a custom item on the launcher context menu.
 * @param {OnClickData} info Event details.
 */
function onContextMenuClicked(info) {
  if (info.menuItemId == 'new-window') {
    // Find the focused window (if any) and use it's current path for the
    // new window. If not found, then launch with the default path.
    for (var key in appWindows) {
      try {
        if (appWindows[key].contentWindow.isFocused()) {
          var appState = {
            defaultPath: appWindows[key].contentWindow.appState.defaultPath
          };
          launchFileManager(appState);
          return;
        }
      } catch (ignore) {
        // The isFocused method may not be defined during initialization.
        // Therefore, wrapped with a try-catch block.
      }
    }

    // Launch with the default path.
    launchFileManager();
  }
}

/**
 * Closes the background page, if it is not needed.
 */
function maybeCloseBackgroundPage() {
  if (Object.keys(appWindows).length === 0 &&
      !FileCopyManager.getInstance().hasQueuedTasks())
    close();
}

/**
 * Initializes the context menu. Recreates if already exists.
 * @param {Object} strings Hash array of strings.
 */
function initContextMenu(strings) {
  try {
    chrome.contextMenus.remove('new-window');
  } catch (ignore) {
    // There is no way to detect if the context menu is already added, therefore
    // try to recreate it every time.
  }
  chrome.contextMenus.create({
    id: 'new-window',
    contexts: ['launcher'],
    title: strings['NEW_WINDOW_BUTTON_LABEL']
  });
}

/**
 * Initializes the background page of Files.app.
 */
function initApp() {
  // Initialize handlers.
  chrome.fileBrowserHandler.onExecute.addListener(onExecute);
  chrome.app.runtime.onLaunched.addListener(onLaunched);
  chrome.app.runtime.onRestarted.addListener(onRestarted);
  chrome.contextMenus.onClicked.addListener(onContextMenuClicked);

  // Fetch strings and initialize the context menu.
  queue.run(function(callback) {
    chrome.fileBrowserPrivate.getStrings(function(strings) {
      initContextMenu(strings);
      chrome.storage.local.set({strings: strings}, callback);
    });
  });
}

// Initialize Files.app.
initApp();
