/*
	Licensed Material - Property of IBM

	(C) Copyright 2015, 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';

var fs = require('fs');
var glob = require('glob');
var log = require('npmlog');
var path = require('path');
var et = require('elementtree');
var Q = require('q');

var moduleName = 'parseNativeAndroid';
/**
    Tries to find metadata out of existing Native Client Project
    @param rootDir: the root directory of where the AndroidManifest.xml exists
    @returns metadata
    {
        'app.version': '1.0.0',
        'app.displayname': 'BlueList',
        'app.id': 'com_ibm_BlueList',
        'app.packagename': 'com.ibm.bluelist'
    }
*/
module.exports = function (rootDirectory){
    var d = Q.defer();

    var clientMetadata = {};

    clientMetadata['app.version'] = "";
    clientMetadata['app.name'] = "";
    clientMetadata['app.dotId'] = "";

    log.silly(moduleName, 'parsing Id and Version out of build.gradle file');
    parseVersionAndId(rootDirectory)
    .then(function (result) {
      log.silly(moduleName, 'found: ' + JSON.stringify(result));
      clientMetadata['app.version'] = result.version;
      clientMetadata['app.dotId'] = result.applicationId;

      log.silly(moduleName, 'parsing name out of AndroidManifest.xml');
      return parseName(rootDirectory);
    })
    .then(function (name) {
      log.silly(moduleName, 'name found to be: ' + name);
      clientMetadata['app.name'] = name;

      d.resolve(clientMetadata);
    })
    .catch(function (err) {
      log.silly('Error parsing android Information. Error:\n' + err.message);
      d.reject();
    });

    return d.promise;
};

function parseVersionAndId(rootDirectory) {
  var version,
      applicationId,
      d = Q.defer();

  try {
    var gradleBuildFilePath = path.resolve(rootDirectory, 'app', 'build.gradle');
    log.silly(moduleName, 'attempting to read build.gradle located at: ' + gradleBuildFilePath);
    var gradleBuildFile = fs.readFileSync(path.resolve(gradleBuildFilePath), {encoding: 'utf8'}).toString();
    log.silly(moduleName, 'build.gradle successfully read');

    //Get version
    var versionName = gradleBuildFile.match('versionName.*');
    if(versionName) {
      var versionRegEx = new RegExp('(versionName .*?")(.*)(")');
      version = versionName[0].replace(versionRegEx, '$2');
      log.silly(moduleName, 'version found to be: ' + version);
    }

    //Get packageName
    var packageName = gradleBuildFile.match('applicationId.*');
    if(packageName) {
      var applicationIdRegEx = new RegExp('(applicationId .*?")(.*)(")');
      applicationId = packageName[0].replace(applicationIdRegEx, '$2');
      log.silly(moduleName, 'applicationId found to be: ' + applicationId);
    }

    d.resolve({
      version: version ? version : '',
      applicationId: applicationId ? applicationId : ''
    });
  } catch (err) {
    d.reject(err);
  }
  return d.promise;
}

function parseName(rootDirectory) {
  var data, etree, index, prefix="";
  var d = Q.defer();

  var androidManifest = glob.sync('**/app/src/main/AndroidManifest.xml', {cwd: rootDirectory});
  if(androidManifest.length !== 0) {
      data = fs.readFileSync(path.join(rootDirectory, androidManifest[0]), {encoding:'utf8'}).toString();
      //To clear BOM marker
      var cleanedString = data.replace("\ufeff", "");
      etree = et.parse(cleanedString);

      var rootAttributes = etree.getroot().items();
      //get prefix for Android namespace
      for(var attribute in rootAttributes){
          if(rootAttributes[attribute][1] === 'http://schemas.android.com/apk/res/android') {
              var key = rootAttributes[attribute][0];
              index = key.indexOf(":");
              prefix = key.substring(index+1) + ":";
              break;
          }
      }

      var label = etree.findall('./application')[0].get(prefix +'label');
      if(label) {
          //Check if the label has @string/
          var getFromStringXML = label.match(/@string\//gi);
          if(getFromStringXML) {
              //get from strings.xml
              data = fs.readFileSync(path.join(rootDirectory, androidManifest[0], '..', 'res', 'values', 'strings.xml'),{encoding:'utf8'}).toString();
              //To clear BOM marker
              data = data.replace("\ufeff", "");
              etree = et.parse(data);
              index = label.indexOf("/");
              var attribName = label.substring(index+1);

              var element = etree.find('./string[@name="'+ attribName +'"]');
              if(element) {
                  label = element.text;
              }
          }
      }

      var appName = label ? label : '';

      d.resolve(appName);
  } else {
    d.reject(new Error('could not find AndroidManifest.xml'));
  }
  return d.promise;
}
