//module for managing yargs commands

var fs = require("fs");
var server = require("./webServer"); // get all modules on "webServer" files
var asciify = require('asciify-image'); // library for create asciify images
var storage = require("node-persist"); // library for read/write account on local container
var {Signale} = require('signale'); // library for handling the output rendering process
var mainFunctions = require("./main"); //get all modules on "main" file

var inquirer = require('inquirer'); //library for use interavtive commands
var yargs = require("yargs");
/**
 * Start application
 */
function start() {

    var accountMatched = null; // for store if account on data encrypted is matched
    const signale = new Signale(); // new signale object for show messages

    //Set commands for CLI mode
    yargs = setCommands();

    storage.initSync(); //initialise set/get variable into machine

    //When start the application ( node app.js )
    if (yargs._[0] == undefined) {

        showWelcome(signale);
    }

    //if command is "generate"
    else if (yargs._[0] == "generate") {
        try {
            var newPassword = mainFunctions.generatePassword();

            signale.success("Password generated! " + newPassword);
            signale.info("Copy this password for use it when you create a new account!");
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "create"
    else if (yargs._[0] == "create") {
        try {

            //Create an object with all option required
            var account = {
                name: yargs.name,
                username: yargs.username,
                password: yargs.password,
                isFavorite: yargs.isFavorite
            };

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {

                    accountMatched = mainFunctions.getAccount(account.name, answers.masterPassword);
                    if (accountMatched != null) {
                        signale.error("This account already exist. If you want, you can modify it");
                    } else {
                        var newAccount = mainFunctions.createAccount(account, answers.masterPassword);
                        if (newAccount) {
                            signale.success("Account " + account.name + " created!");
                        }
                    }
                })
        }
        catch (err) {
            throw err;
        }
    }

    //if command is "get"
    else if (yargs._[0] == "get") {
        try {
            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    accountMatched = mainFunctions.getAccount(yargs.name, answers.masterPassword);
                    if (accountMatched != null) {
                        signale.success("Account matched!");
                        signale.info("Name: " + accountMatched.name);
                        signale.info("Username: " + accountMatched.username);
                        signale.info("Password: " + accountMatched.password);
                        signale.info("Favorite: " + accountMatched.isFavorite);
                    } else {
                        signale.error("This account not exist!");
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "modify"
    else if (yargs._[0] == "modify") {
        try {

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    accountMatched = mainFunctions.getAccount(yargs.name, answers.masterPassword);
                    if (accountMatched != null) {
                        signale.success("Account matched!");

                        var newAccount = mainFunctions.modifyAccount(accountMatched,
                            { name: yargs.name, username: yargs.newUsername, password: yargs.newPassword, isFavorite: yargs.isFavorite }, answers.masterPassword);

                        if (newAccount.length == 0) {
                            signale.error("Missing parameters!")
                        } else {
                            signale.success("Account changed!")
                            signale.info("Name: " + newAccount.name);
                            signale.info("Username: " + newAccount.username);
                            signale.info("Password: " + newAccount.password);
                            signale.info("Favorite: " + newAccount.isFavorite);
                        }
                    } else {
                        signale.error("This account not exist!");
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "getList"
    else if (yargs._[0] == "getList") {
        try {

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    var list = mainFunctions.getAccounts(answers.masterPassword);
                    if (list) {
                        if (list.length > 0) {

                            list.forEach(function (currentAccount, index) {

                                index = index + 1;
                                signale.start("Details of accounts " + index++ + ": \n");
                                signale.info("Name: " + currentAccount.name);
                                signale.info("Username: " + currentAccount.username);
                                signale.info("Password: " + currentAccount.password);
                                if (currentAccount.isFavorite) {
                                    signale.info("Favorite: " + currentAccount.isFavorite);
                                } else {
                                    signale.info("Favorite: " + false + "\n");
                                }
                            })
                        } else {
                            signale.error("No accounts!");
                        }
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "getListFavorites"
    else if (yargs._[0] == "getListFavorites") {
        try {

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    var list = mainFunctions.getAccounts(answers.masterPassword);
                    if (list) {
                        if (list.length > 0) {

                            list.forEach(function (currentAccount, index) {

                                if (currentAccount.isFavorite) {
                                    index = index + 1;
                                    signale.start("Details of accounts " + index++ + ": \n");
                                    signale.info("Name: " + currentAccount.name);
                                    signale.info("Username: " + currentAccount.username);
                                    signale.info("Password: " + currentAccount.password);
                                    signale.info("Favorite: " + currentAccount.isFavorite + "\n");
                                }
                            })
                        } else {
                            signale.error("No accounts!");
                        }
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "deleteAccount"
    else if (yargs._[0] == "deleteAccount") {
        try {

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    accountMatched = mainFunctions.getAccount(yargs.name, answers.masterPassword);
                    if (accountMatched != null) {

                        mainFunctions.deleteAccount(yargs.name, answers.masterPassword);
                        signale.success("Account " + yargs.name + " deleted!");

                    } else {
                        signale.error("This account not exist!");
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "deleteAll"
    else if (yargs._[0] == "deleteAll") {
        try {

            inquirer.prompt([
                {
                    type: 'password',
                    message: 'Enter your master password',
                    name: 'masterPassword',
                    mask: "*"
                }
            ])
                .then(function (answers) {
                    accountMatched = mainFunctions.getAccounts(answers.masterPassword); // for control masterpassword
                    if (accountMatched != null) {
                        //delete file accounts
                        fs.unlink("./persist/accounts", function () {
                            signale.success("Accounts deleted!");
                        })
                    } else {
                        signale.error("This account not exist!");
                    }
                })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "backup"
    else if (yargs._[0] == "backup") {
        try {

            //Get account container
            var data = storage.getItemSync("accounts");

            fs.writeFile("./backup/backup.txt", data, function () {
                signale.success("Backup created!");
            })
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "restore"
    else if (yargs._[0] == "restore") {
        try {
            if (!fs.existsSync("-/backup") && !fs.existsSync("./backup/backup.txt")) {
                signale.error("You not have a backup");
            } else {
                fs.readFile("./backup/backup.txt", "", function (err, dataFile) {
                    if (err) {
                        throw err;
                    }
                    storage.setItemSync("accounts", dataFile.toString()); //insert into variableStorage called "accounts" the entire array
                    signale.success("Accounts restored!");
                })
            }
        } catch (e) {
            signale.fatal(e);
        }
    }

    //if command is "web"
    else if (yargs._[0] == "web") {

        server.startServer(); // load startServer module

    } else {
        signale.error("This command not exist!");
    }
}

/**
 * Show welcome
 * @param {*} signale -> Signale object for show messages
 */
function showWelcome(signale)  {
    var optionsAsciify = {
        fit: 'box',
        width: 15,
        height: 15
    };
    asciify('./img/download.jpeg', optionsAsciify, function (err, asciified) {
        if (err) {
            throw err;
        }

        //options for custom signale object
        const options = {
            disabled: false,
            interactive: false,
            logLevel: 'info',
            scope: 'custom',
            secrets: [],
            types: {
                PasswordManager: {
                    color: 'blue',
                    label: 'PasswordManager',
                    logLevel: 'info'
                }
            }
        };

        //other signale object for create a custom message for init
        const customSignale = new Signale(options);
        customSignale.PasswordManager(asciified);

        // ask mode
        inquirer.prompt([
            {
                type: 'list',
                message: 'Select mode that you would like to use:',
                name: 'mode',
                default: 'web',
                choices: [
                    {
                        name: "Web mode",
                        value: "web",
                    },
                    {
                        name: "Command line",
                        value: "cli",
                    }
                ]
            }
        ]).then(function (answer) {
            if (answer.mode == "web") {
                server.startServer(); // load startServer module
            } else if (answer.mode == "cli") {
                signale.start("Welcome on password manager! Please enter 'node app.js --help' command for see all commands available!");
                signale.warn("For security reason, remember your master password or you will not decrypt your accounts!");
            }
        })
    });
}

/**
 * Set commands for CLI mode
 */
function setCommands()  {

    var yargsObj = require("yargs")
        .command("generate", "Generate a new password", function (generateCmd) {
            generateCmd.help("help");
        }).help("help")

        .command("create", "Create a new account", function (createCmd) {  //define a new command for use it from command line
            createCmd.options({ //define a options/properties of arguments
                name: {
                    demand: true,
                    alias: "n",
                    description: "Account name (ex: Twitter, Facebook ecc..)",
                    type: "String"
                },
                username: {
                    demand: true,
                    alias: "u",
                    description: "Insert your username of your account",
                    type: "String"
                },
                password: {
                    demand: true,
                    alias: "p",
                    description: "Insert your password",
                    type: "String"
                },
                isFavorite: {
                    demand: true,
                    alias: "f",
                    description: "add into favorite list",
                    type: "Boolean"
                }

            }).help("help"); //create an interactive helper
        }).help("help")

        .command("get", "Get an existing account", function (getCmd) {
            getCmd.options({
                name: {
                    demand: true,
                    alias: "n",
                    description: "Insert an existing account ( es Facebook, Twitter ecc...)",
                    type: "String"
                }
            }).help("help");

        }).help("help")

        .command("modify", "Modify an existing account", function (modifyCmd) {
            modifyCmd.options({
                name: {
                    demand: true,
                    alias: "en",
                    description: "Insert an existing name account ( es Facebook, Twitter ecc...)",
                    type: "String"
                },
                newUsername: {
                    demand: false,
                    alias: "u",
                    description: "Insert new username",
                    type: "String"
                },
                newPassword: {
                    demand: false,
                    alias: "p",
                    description: "Insert new password",
                    type: "String"
                },
                isFavorite: {
                    demand: true,
                    alias: "f",
                    description: "add into favorite list",
                    type: "Boolean"
                }
            }).help("help");

        }).help("help")

        .command("getList", "Get list accounts", function () {
            //no options
        }).help("help")

        .command("getListFavorites", "Get list favorites accounts", function () {
            //no options
        }).help("help")

        .command("deleteAccount", "Delete a specific account", function (deleteAccountCmd) {
            deleteAccountCmd.options({
                name: {
                    demand: true,
                    alias: "n",
                    description: "Account name (ex: Twitter, Facebook ecc..)",
                    type: "String"
                }
            }).help("help");
        }).help("help")

        .command("deleteAll", "Delete all accounts", function () {
            //no options
        }).help("help")

        .command("backup", "Backup your encrypted accounts", function () {
            //no options
        }).help("help")

        .command("restore", "Restore your encrypted accounts from existing backup file", function () {
            //no options
        }).help("help")

        .command("web", "Use web mode", function () {
            //no options
        }).help("help")    
    .argv;

    return yargsObj;
}
exports.start = start;