# -*- coding: utf-8 -*-

""" License

    Copyright (C) 2013 YunoHost

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program; if not, see http://www.gnu.org/licenses

"""

""" yunohost_hook.py

    Manage hooks
"""
import os
import sys
import re
import json
import errno

from moulinette.core import MoulinetteError

hook_folder = '/usr/share/yunohost/hooks/'

def hook_add(app, file):
    """
    Store hook script to filsystem

    Keyword argument:
        app -- App to link with
        file -- Script to add (/path/priority-file)

    """
    path, filename = os.path.split(file)
    if '-' in filename:
        priority, action = filename.split('-')
    else:
        priority = '50'
        action = filename

    try: os.listdir(hook_folder + action)
    except OSError: os.makedirs(hook_folder + action)

    finalpath = hook_folder + action +'/'+ priority +'-'+ app
    print app
    os.system('cp %s %s' % (file, finalpath))
    os.system('chown -hR admin: %s' % hook_folder)

    return { 'hook': finalpath }


def hook_remove(app):
    """
    Remove hooks linked to a specific app

    Keyword argument:
        app -- Scripts related to app will be removed

    """
    try:
        for action in os.listdir(hook_folder):
            for script in os.listdir(hook_folder + action):
                if script.endswith(app):
                    os.remove(hook_folder + action +'/'+ script)
    except OSError: pass


def hook_callback(action, args=None):
    """
    Execute all scripts binded to an action

    Keyword argument:
        action -- Action name
        args -- Ordered list of arguments to pass to the script

    """
    try: os.listdir(hook_folder + action)
    except OSError: pass
    else:
        if args is None:
            args = []
        elif not isinstance(args, list):
            args = [args]

        for hook in os.listdir(hook_folder + action):
            try:
                hook_exec(file=hook_folder + action +'/'+ hook, args=args)
            except: pass


def hook_check(file):
    """
    Parse the script file and get arguments

    Keyword argument:
        file -- File to check

    """
    try:
        with open(file[:file.index('scripts/')] + 'manifest.json') as f:
            manifest = json.loads(str(f.read()))
    except:
        raise MoulinetteError(errno.EIO, m18n.n('app_manifest_invalid'))

    action = file[file.index('scripts/') + 8:]
    if 'arguments' in manifest and action in manifest['arguments']:
        return manifest['arguments'][action]
    else:
        return {}


def hook_exec(file, args=None):
    """
    Execute hook from a file with arguments

    Keyword argument:
        file -- Script to execute
        args -- Arguments to pass to the script

    """
    if isinstance(args, list):
        arg_list = args
    else:
        required_args = hook_check(file)
        if args is None:
            args = {}

        arg_list = []
        for arg in required_args:
            if arg['name'] in args:
                if 'choices' in arg and args[arg['name']] not in arg['choices']:
                    raise MoulinetteError(errno.EINVAL,
                                          m18n.n('hook_choice_invalid')
                                                  % args[arg['name']])
                arg_list.append(args[arg['name']])
            else:
                if os.isatty(1) and 'ask' in arg:
                    # Retrieve proper ask string
                    ask_string = None
                    for lang in [m18n.locale, m18n.default_locale]:
                        if lang in arg['ask']:
                            ask_string = arg['ask'][lang]
                            break
                    if not ask_string:
                        # Fallback to en
                        ask_string = arg['ask']['en']

                    # Append extra strings
                    if 'choices' in arg:
                        ask_string += ' (%s)' % '|'.join(arg['choices'])
                    if 'default' in arg:
                        ask_string += ' (default: %s)' % arg['default']

                    input_string = msignals.prompt(ask_string)

                    if input_string == '' and 'default' in arg:
                        input_string = arg['default']

                    arg_list.append(input_string)
                elif 'default' in arg:
                    arg_list.append(arg['default'])
                else:
                    raise MoulinetteError(errno.EINVAL,
                                          m18n.n('hook_argument_missing')
                                                  % arg['name'])

    file_path = "./"
    if "/" in file and file[0:2] != file_path:
        file_path = os.path.dirname(file)
        file = file.replace(file_path +"/", "")
    return os.system('su - admin -c "cd \\"%s\\" && bash \\"%s\\" %s"' % (file_path, file, ' '.join(arg_list))) 
    #TODO: Allow python script