#!/usr/bin/env node
"use strict";

var meow          = require("meow");
var fs            = require("fs");
var path          = require("path");
var compile       = require("eazy-logger").compile;
var _             = require("lodash");
var utils         = require("../lib/utils");
var flags         = require("../lib/cli/opts");
var info          = require("../lib/cli/cli-info");
var logger        = require("../lib/logger").logger;

var cmdWhitelist  = ["start", "init"];
var flagWhitelist = Object.keys(flags).map(dropPrefix).map(_.camelCase);

var cli = meow({
    pkg:  "../package.json",
    help: getHelpText(path.resolve(__dirname, "../lib/cli/help.txt"))
});


/**
 * Handle cli input
 */
if (!module.parent) {
    handleCli({cli: cli, whitelist: cmdWhitelist});
}

/**
 * Generate & colour the help text
 * @param {String} filepath - relative file path to the help text
 * @returns {String}
 */
function getHelpText(filepath) {
    return compile(
        fs.readFileSync(
            filepath,
            "utf8"
        ).replace(
            "%flags%",
            listFlags(
                flags,
                longest(
                    Object.keys(flags)
                ).length
            )
        )
    );
}

/**
 * @param {{cli: object, [whitelist]: array, [cb]: function}} opts
 * @returns {*}
 */
function handleCli (opts) {

    opts.cb = opts.cb || utils.defaultCallback;

    var input = opts.cli.input;
    var flags = opts.cli.flags;

    if (!opts.whitelist) {
        opts.whitelist = cmdWhitelist;
    }

    if (!input.length || opts.whitelist.indexOf(input[0]) === -1) {
        return console.log(opts.cli.help);
    }

    if (!verifyOpts(flagWhitelist, flags)) {
        logger.info("For help, run: {cyan:browser-sync --help}");
        return opts.cb(new Error("Unknown flag given. Please refer to the documentation for help."));
    }

    if (input[0] === "start") {
        return require("../")
            .create("cli")
            .init(flags.config ? info.getConfigFile(flags.config) : flags, opts.cb);
    }

    if (input[0] === "init") {
        info.makeConfig(process.cwd(), opts.cb);
    }
}

/**
 * @param {Array} flagWhitelist
 * @param {Object} cliFlags
 * @returns {Boolean}
 */
function verifyOpts (flagWhitelist, cliFlags) {
    return Object.keys(cliFlags).every(function (key) {
        if (flagWhitelist.indexOf(key) > -1) {
            return true;
        }
        if (!(key in flags)) {
            if (!("no-" + key in flags)) {
                logger.info("Unknown flag:  {yellow:`%s`", key);
                return false;
            }
        }
        return true;
    });
}

/**
 * @param {Object} flags
 * @param {Number} longest
 * @returns {String}
 */
function listFlags (flags, longest) {
    return Object.keys(flags).reduce(function (all, item) {
        return all + "    {bold:--" + item + "}" + getPadding(item.length, longest + 8) + flags[item] + "\n";
    }, "");
}

/**
 * @param {Number} len
 * @param {Number} max
 * @returns {string}
 */
function getPadding (len, max) {
    return new Array(max - (len + 1)).join(" ");
}

/**
 * @param {Array} arr
 * @returns {String}
 */
function longest (arr) {
    return arr.sort(function (a, b) { return b.length - a.length; })[0];
}

/**
 * @param {String} item
 * @returns {String}
 */
function dropPrefix (item) {
    return item.replace("no-", "");
}

module.exports = handleCli;
module.exports.getHelpText = getHelpText;
@@ -317,24 +317,64 @@
 cli/opts%22);%0A
+var flagKeys      = Object.keys(flags);%0A
 var info    
@@ -526,34 +526,24 @@
 elist = 
-Object.keys(flags)
+flagKeys
 .map(dro
@@ -1179,34 +1179,24 @@
         
-Object.keys(flags)
+flagKeys
 %0A       
@@ -2296,24 +2296,25 @@
 cliFlags) %7B%0A
+%0A
     return O
@@ -2353,24 +2353,25 @@
 ion (key) %7B%0A
+%0A
         if (
@@ -2369,16 +2369,27 @@
      if 
+(_.contains
 (flagWhi
@@ -2398,26 +2398,43 @@
 list
-.indexOf(key) %3E -1
+, key) %7C%7C _.contains(flagKeys, key)
 ) %7B%0A
@@ -2472,90 +2472,9 @@
   %7D%0A
-        if (!(key in flags)) %7B%0A            if (!(%22no-%22 + key in flags)) %7B%0A        
+%0A
     
@@ -2526,24 +2526,17 @@
 , key);%0A
-        
+%0A
         
@@ -2553,53 +2553,8 @@
 se;%0A
-            %7D%0A        %7D%0A        return true;%0A
     
@@ -2690,34 +2690,24 @@
  return 
-Object.keys(flags)
+flagKeys
 .reduce(

simplify CLI input