/*
 *
 * 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(path.resolve(project_dir, config_xml_filename), '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));
    }
}
