/*
	Licensed Material - Property of IBM

	(C) Copyright 2016 IBM Corp.

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/


'use strict';

//private modules
var messages = require('./externalizedStrings');
var strings = require('ibm-strings');
var errors = require('mdo-errors');
var ConfigXMLAPI = require('mfp-config-xml');

//public modules
var path = require('path');
var fs = require('fs');
var log = require('npmlog');
var Q = require('q');

var moduleName = 'webupdate-fileProvidedPath';

/**
 Function that executes the path of webupdate when the --file flag was used.
 This function simply reads the file, validates the file, and then deploys it to the server
 @param filePath - file path of the file to deploy
 @param platforms - The platforms array that is returned from the platformDetection function of the platform manager
 @param serverDetails - The server details object returned from the getServerDetails function of mdo-server
**/
module.exports = function fileProvidedPath(filePath, platforms, serverDetails) {
  var platform,
      d = Q.defer();

  log.silly(moduleName, 'Verifying file exists');
  verifyFile(filePath)
  .then(function () {
    log.silly(moduleName, 'Extracting platfrom from filename');
    return determineFilePlatform(filePath);
  })
  .then(function (filePlatform) {
    platform = filePlatform;
    log.silly(moduleName, 'Platform determined to be: ' + filePlatform);
    var applicationKey = generateWebUpdateJSON(filePlatform, platforms.platforms[0].configXMLPath);
    return serverDetails.deployWebupdate(applicationKey, filePath);
  })
  .then(function () {
    strings.info(strings.format(messages.deployedApp, platform));
    d.resolve();
  })
  .catch(function (err) {
    log.silly('fileProvidedPath catch block executed, err: ' + err);
    d.reject(err);
  });

  return d.promise;
};

/**
  Function to generate the JSON to send to the server to let it know what app to deploy the resources for
  @param platform - the platform of the file
  @param configXMLPath - the path to the config.xml.
**/
function generateWebUpdateJSON(platform, configXMLPath) {
  var configXML = new ConfigXMLAPI.mfpConfigXMLAPI(configXMLPath);
  var idName;
  if(platform === 'android') {
      idName = 'packageName';
  } else if(platform === 'ios') {
      idName = 'bundleId';
  } else {
      idName = 'assemblyName';
  }

  var applicationKey = {
      version: configXML.getWidgetVersion(),
      clientPlatform: platform,
  };
  applicationKey[idName] = configXML.getWidgetId();

  log.silly(moduleName, 'ApplicationKey generated for deployment to server. Key is: ' + JSON.stringify(applicationKey));
  return applicationKey;
}

/**
  Function to validate certain parts of the zip fileStat
  Checks that the file is a valid .zip format. Also checks that the file exists
**/
function verifyFile(file) {
  var d = Q.defer();

  try {
    var fileStat = fs.statSync(file);
    log.silly(moduleName, 'verifying file is a zip file');
    if(fileStat.isFile() && path.extname(file) === '.zip') {
      log.silly(moduleName, 'file is a zip, resolving');
      d.resolve();
    } else {
      var invalidFileErr = errors.getError("UPDATEFILENOTVALIDZIPFILE", file);
      d.reject(invalidFileErr);
    }
  } catch (err) {
    var fileDoesNotExistErr = errors.getError('FILENOEXISTS', file);
    d.reject(fileDoesNotExistErr);
  }

  return d.promise;
}

/**
  Function to validate the filename and peel out the platform type
   So if the filename is my.cordova.project-{platform}-0.0.1.zip , so it would pull off that {platform}
   This function will reject the promise as well if that platform is determine to not be a vliad platform
   valid platforms are {android, ios, windows, windows8, windowsphone8, browser}
   If the platform is Windows or browser then an error is thrown mentioning windows browser is not supported currently.
   @param filePath - the filePath of the file
**/
function determineFilePlatform(filePath) {
  var d = Q.defer();

  var basename = path.basename(filePath);
  //Just in case they have a platform id in their file name lets do some logic to prevent that
  var lastIndexOfDash = basename.lastIndexOf('-');
  var dashBeforePlatformId = basename.lastIndexOf('-', lastIndexOfDash-1);

  var platform = basename.substring(dashBeforePlatformId+1, lastIndexOfDash);

  if(platform === 'android' || platform === 'ios') {
    d.resolve(platform);
  } else if (platform.indexOf('windows') >= 0) {
    var windowsNotSupportedErr = errors.getError('WINDOWSNOTSUPPORTEDWEBUPDATE', platform);
    d.reject(windowsNotSupportedErr);
} else if (platform.indexOf('browse') >= 0) {
    var browserNotSupportedErr = errors.getError('BROWSERNOTSUPPORTEDWEBUPDATE', platform);
    d.reject(browserNotSupportedErr);
} else {
    var invalidFileNameErr = errors.getError('INVALIDFILENAMEWEBUPDATE', basename);
    d.reject(invalidFileNameErr);
  }

  return d.promise;
}
