/*
 *
 * Copyright 2013 Anis Kadri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 *
*/

var path = require('path')
  , fs = require('../util/fs')  // use existsSync in 0.6.x
  , glob = require('glob')
  , et = require('elementtree')
  , xcode = require('xcode')
  , plist = require('plist')
  , bplist = require('bplist-parser')
  , shell = require('shelljs')
  , xml_helpers = require('../util/xml-helpers')
  , plist_helpers = require('../util/plist-helpers')
  , getConfigChanges = require('../util/config-changes')
  , searchAndReplace = require('../util/search-and-replace')
  , getConfigChanges = require('../util/config-changes')
  , assetsDir = 'www';    // relative path to project's web assets

exports.handlePlugin = function (action, project_dir, plugin_dir, plugin_et, variables) {
    var plugin_id = plugin_et._root.attrib['id']
      , version = plugin_et._root.attrib['version']
      , i = 0
      , matched;
    variables = variables || {}

    // grab and parse pbxproj
    // we don't want CordovaLib's xcode project
    var project_files = glob.sync(project_dir + '/*.xcodeproj/project.pbxproj');
    
    if (!project_files.length) throw new Error("does not appear to be an xcode project (no xcode project file)");
    var pbxPath = project_files[0];

    var xcodeproj = xcode.project(project_files[0]);
    xcodeproj.parseSync();

    // grab and parse plist file or config.xml
    var config_files = (glob.sync(project_dir + '/**/{PhoneGap,Cordova}.plist').length == 0 ? 
                        glob.sync(project_dir + '/**/config.xml') :
                        glob.sync(project_dir + '/**/{PhoneGap,Cordova}.plist')
                       );

    config_files = config_files.filter(function (val) {
        return !(/^build\//.test(val));
    });

    if (!config_files.length) {
        throw new Error("does not appear to be a PhoneGap project");
    }

    var config_file = config_files[0];
    var xcode_dir = path.dirname(config_file);
    var pluginsDir = path.resolve(xcode_dir, 'Plugins');
    var resourcesDir = path.resolve(xcode_dir, 'Resources');
    
    // get project plist for package name
    var project_plists = glob.sync(xcode_dir + '/*-Info.plist');
    var projectPListPath = project_plists[0];
    
    // collision detection 
    if(action.match(/force-/) == null) {
      if(action == "install" && pluginInstalled(plugin_et, config_file)) {
          throw new Error("Plugin "+plugin_id+" already installed")
      } else if(action == "uninstall" && !pluginInstalled(plugin_et, config_file)) {
          throw new Error("Plugin "+plugin_id+" not installed")
      }
    } else {
      action = action.replace('force-', '');
    }
    
    var assets = plugin_et.findall('./asset'),
        platformTag = plugin_et.find('./platform[@name="ios"]'),
        sourceFiles = platformTag.findall('./source-file'),
        headerFiles = platformTag.findall('./header-file'),
        resourceFiles = platformTag.findall('./resource-file'),
        frameworks = platformTag.findall('./framework'),
        configChanges = getConfigChanges(platformTag);

    // move asset files into www
    assets && assets.forEach(function (asset) {
        var srcPath = path.resolve(
                        plugin_dir, asset.attrib['src']);

        var targetPath = path.resolve(
                            project_dir,
                            assetsDir, asset.attrib['target']);
        if (action == 'install') {
            var stat = fs.statSync(srcPath);
            if(stat.isDirectory()) {
              shell.mkdir('-p', targetPath);
              checkLastCommand();
              shell.cp('-r', srcPath, targetPath);
              checkLastCommand();
            } else {
              shell.cp(srcPath, targetPath);
            }
            checkLastCommand();
        } else {
            shell.rm('-rf', targetPath);
            checkLastCommand();
        }
    });

    // move native files (source/header/resource)
    sourceFiles && sourceFiles.forEach(function (sourceFile) {
        var src = sourceFile.attrib['src'],
            srcFile = path.resolve(plugin_dir, 'src/ios', src),
            targetDir = path.resolve(pluginsDir, getRelativeDir(sourceFile)),
            destFile = path.resolve(targetDir, path.basename(src));
         
        if (action == 'install') {
            xcodeproj.addSourceFile('Plugins/' + path.relative(pluginsDir, destFile));
            shell.mkdir('-p', targetDir);
            checkLastCommand();
            shell.cp(srcFile, destFile);
            checkLastCommand();
        } else {
            xcodeproj.removeSourceFile('Plugins/' + path.basename(src));   
            if(fs.existsSync(destFile))
                fs.unlinkSync(destFile);
            shell.rm('-rf', targetDir);    
            checkLastCommand();
        }
    });

    headerFiles && headerFiles.forEach(function (headerFile) {
        var src = headerFile.attrib['src'],
            srcFile = path.resolve(plugin_dir, 'src/ios', src),
            targetDir = path.resolve(pluginsDir, getRelativeDir(headerFile)),
            destFile = path.resolve(targetDir, path.basename(src));
         
        if (action == 'install') {     
            xcodeproj.addHeaderFile('Plugins/' + path.relative(pluginsDir, destFile));
            shell.mkdir('-p', targetDir);
            checkLastCommand();
            shell.cp(srcFile, destFile);
            checkLastCommand();
        } else {
            xcodeproj.removeHeaderFile('Plugins/' + path.basename(src));
            if(fs.existsSync(destFile))
                fs.unlinkSync(destFile);
            shell.rm('-rf', targetDir);
            checkLastCommand();
        }
    });

    resourceFiles && resourceFiles.forEach(function (resource) {
        var src = resource.attrib['src'],
            srcFile = path.resolve(plugin_dir, 'src/ios', src),
            destFile = path.resolve(resourcesDir, path.basename(src));

        if (action == 'install') {
            xcodeproj.addResourceFile('Resources/' + path.basename(src));
            var st = fs.statSync(srcFile);
            if (st.isDirectory()) {
                shell.cp('-R', srcFile, resourcesDir);
                checkLastCommand();
            } else {
                shell.cp(srcFile, destFile);
                checkLastCommand();
            }
        } else {
            xcodeproj.removeResourceFile('Resources/' + path.basename(src));
            shell.rm('-rf', destFile);
            checkLastCommand();
        }
    });

    frameworks && frameworks.forEach(function (framework) {
        var src = framework.attrib['src'],
            weak = framework.attrib['weak'];

        if (action == 'install') {
            var opt = { weak: (weak && weak.toLowerCase() == 'true') };
            xcodeproj.addFramework(src, opt);
        } else {
            xcodeproj.removeFramework(src);
        }
    });

    // write out xcodeproj file
    fs.writeFileSync(pbxPath, xcodeproj.writeSync());

    try {
      // add plugin and whitelisted hosts
      updateConfig(action, config_file, plugin_et);
      
      // edit custom configuration items
      Object.keys(configChanges).forEach(function (filename) {
          var filepaths = glob.sync(path.resolve(xcode_dir, filename));
          for (var i in filepaths) {
              updateCustomConfig(action, filepaths[i], configChanges[filename]);
          }
      });
    } catch(e) {
      throw {
        name: "ConfigurationError",
        level: "ERROR",
        message: "Error updating configuration: "+e.message,
      }
    }
    
    if (action == 'install') {
        variables['PACKAGE_NAME'] = plist.parseFileSync(projectPListPath).CFBundleIdentifier;
        searchAndReplace(pbxPath, variables);
        searchAndReplace(projectPListPath, variables);
        searchAndReplace(config_file, variables);
    }
    
}

function getRelativeDir(file) {
    var targetDir = file.attrib['target-dir'],
        preserveDirs = file.attrib['preserve-dirs'];

    if (preserveDirs && preserveDirs.toLowerCase() == 'true') {
        return path.dirname(file.attrib['src']);
    } else if (targetDir) {
        return targetDir;
    } else {
        return '';
    }
}

// determine if a plist file is binary
function isBinaryPlist(filename) {
    // I wish there was a synchronous way to read only the first 6 bytes of a
    // file. This is wasteful :/ 
    var buf = '' + fs.readFileSync(filename, 'utf8');
    // binary plists start with a magic header, "bplist"
    return buf.substring(0, 6) === 'bplist';
}

function updatePlistFile(action, config_path, plugin_et) {
    var hosts = plugin_et.findall('./access'),
        platformTag = plugin_et.find('./platform[@name="ios"]'), // FIXME: can probably do better than this
        plistEle = platformTag.find('./plugins-plist'),
        external_hosts = [];

    // determine if this is a binary or ascii plist and choose the parser
    // this is temporary until binary support is added to node-plist
    var pl = (isBinaryPlist(config_path) ? bplist : plist);

    var plistObj = pl.parseFileSync(config_path);
    
    if (action == 'install') {
        // add hosts to whitelist (ExternalHosts) in plist
        hosts && hosts.forEach(function(host) {
            plistObj.ExternalHosts.push(host.attrib['origin']);
        });

        // add plugin to plist
        plistObj.Plugins[plistEle.attrib['key']] = plistEle.attrib['string'];
    } else {
        // remove hosts from whitelist (ExternalHosts) in plist
        // check each entry in external hosts, only add it to the plist if
        // it's not an entry added by this plugin 
        for(i=0; i < plistObj.ExternalHosts.length;i++) {
            matched = false;
            hosts && hosts.forEach(function(host) {
                if(host.attrib.origin === plistObj.ExternalHosts[i]) {
                    matched = true;
                }
            });

            if (!matched) {
                external_hosts.push(plistObj.ExternalHosts[i]);
            }
        }

        // filtered the external hosts entries out, copy result
        plistObj.ExternalHosts = external_hosts;

        delete plistObj.Plugins[plistEle.attrib['key']];
    }
    
    // write out plist
    fs.writeFileSync(config_path, plist.build(plistObj));
}

function pluginInstalled(plugin_et, config_path) {
    var config_tag = plugin_et.find('./platform[@name="ios"]/config-file[@target="config.xml"]/plugin') ||
                     plugin_et.find('./platform[@name="ios"]/plugins-plist');
    if (!config_tag) {
        return false;
    }
    var plugin_name = config_tag.attrib.name || config_tag.attrib.key,
        plugin_id = plugin_et._root.attrib['id'],
        readfile = fs.readFileSync(config_path, 'utf8');
    if ((readfile.match(new RegExp(plugin_name, "g")) != null) || (readfile.match(new RegExp(plugin_id, "g")) != null)){
        return true;
    }
}

function updateConfigXml(action, config_path, plugin_et) {
    var hosts = plugin_et.findall('./access'),
        platformTag = plugin_et.find('./platform[@name="ios"]'), // FIXME: can probably do better than this
        plistEle = platformTag.find('./plugins-plist'), // use this for older that have plugins-plist
        configChanges = getConfigChanges(platformTag),
        base_config_path = path.basename(config_path);

    // edit configuration files
    var xmlDoc = xml_helpers.parseElementtreeSync(config_path),
        output,
		    pListOnly = plistEle;
    
    if (configChanges[path.basename(config_path)]) {	
      configChanges[path.basename(config_path)].forEach(function (val) {
        if (val.find("plugin")) pListOnly = false;
      });
    }

    if (pListOnly) {
        // if the plugin supports the old plugins-plist element only
        var name = plistEle.attrib.key;
        var value = plistEle.attrib.string;
        var pluginsEl = xmlDoc.find('plugins');
        if ( action == 'install') {
            var new_plugin = new et.Element('plugin');
            new_plugin.attrib.name = name;
            new_plugin.attrib.value = value;
            pluginsEl.append(new_plugin);
        } else {
            var culprit = pluginsEl.find("plugin[@name='"+name+"']");
            pluginsEl.remove(0, culprit);
        }
    }

    // add whitelist hosts
    root = et.Element("config-file");
    root.attrib['parent'] = '.'
      hosts.forEach(function (tag) {
      root.append(tag);
    });

    if (root.len()) {
      (configChanges[path.basename(config_path)]) ?
            configChanges[path.basename(config_path)].push(root) :
            configChanges[path.basename(config_path)] = [root];
    }

    if (configChanges[path.basename(config_path)]) {

        configChanges[base_config_path].forEach(function (configNode) {
            var selector = configNode.attrib["parent"],
                children = configNode.findall('*');
            if( action == 'install') {
                if (!xml_helpers.graftXML(xmlDoc, children, selector)) {
                    throw new Error('failed to add children to ' + selector + ' in ' + config_path);
                }
            } else {
                if (!xml_helpers.pruneXML(xmlDoc, children, selector)) {
                    throw new Error('failed to remove children from ' + selector + ' in ' + config_path);
                }
            }
            delete configChanges[base_config_path][configNode];
        });
    }

    output = xmlDoc.write({indent: 4});
    fs.writeFileSync(config_path, output);
}

// updates plist file and/or config.xml
function updateConfig(action, config_path, plugin_et) {
    if(path.basename(config_path) == "config.xml") {
        updateConfigXml(action, config_path, plugin_et);
    } else {
        updatePlistFile(action, config_path, plugin_et);
    }
}

// throws error if last command returns code != 0
function checkLastCommand() {
    if(shell.error() != null) throw {name: "ShellError", message: shell.error()};
}

// updates plist file and/or config.xml
function updateCustomConfig(action, filepath, configNodes) {

    if (path.extname(filepath) == ".xml") {
        var xmlDoc = xml_helpers.parseElementtreeSync(filepath),
            output;

        configNodes.forEach(function (configNode) {
            var selector = configNode.attrib["parent"],
                children = configNode.findall('*');
            
            if( action == 'install') {
                if (!xml_helpers.graftXML(xmlDoc, children, selector)) {
                    throw new Error('failed to add children to ' + filepath);
                }
            } else {
                if (!xml_helpers.pruneXML(xmlDoc, children, selector)) {
                    throw new Error('failed to remove children from' + filepath);
                }
            }
        });
        
        output = xmlDoc.write({indent: 4});
        fs.writeFileSync(filepath, output);
        
    }
    else { // PLIST
        var pl = (isBinaryPlist(filepath) ? bplist : plist),
            plistObj = pl.parseFileSync(filepath);

        configNodes.forEach(function (configNode) {

            var selector = configNode.attrib["parent"],
                children = configNode.find("./*");

            if( action == 'install') {
                if (!plist_helpers.graftPLIST(plistObj, children, selector)) {
                    throw new Error('failed to add children to ' + filepath);
                }
            } else {
                if (!plist_helpers.prunePLIST(plistObj, children, selector)) {
                    throw new Error('failed to remove children from' + filepath);
                }
            }

        });

        // write out plist
        fs.writeFileSync(filepath, plist.build(plistObj));
    }
}
