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

# Copyright 2012 Calculate Ltd. http://www.calculate-linux.org
#
#  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.

import argparse, sys
from function import _create_obj, get_view_params, print_brief
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_console3',sys.modules[__name__])
import urllib2

from calculate.core.server.methods_func import get_method_argparser, \
                              collect_object, RawAndDefaultsHelpFormatter, \
                              check_result_msg, get_param_pwd, getErrorOnParam

def parse():
    parser = argparse.ArgumentParser(add_help=False,
                                 formatter_class=RawAndDefaultsHelpFormatter)
#    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument(
        '-h', '--help', action='store_true', default=False,
        dest='help', help=_("show this help message and exit"))
    parser.add_argument(
        '--method', type=str, dest='method', help=_('call method'))
    parser.add_argument(
        '-l', '--lang', type=str, dest='lang',
        help=_('translation language'))
    parser.add_argument(
        '-p', '--port', type=int, default = '8888', dest='port',
        help=_('port number'))
    parser.add_argument(
        '--host', type=str, default = 'localhost', dest='host',
        help=_('destination host'))
    parser.add_argument(
        '--gen-cert-by', type=str, dest='by_host', metavar = 'HOST',
        help = \
           _('send a certificate signature request to the server'))
    parser.add_argument(
        '--get-cert-from', type=str, dest='from_host', metavar = 'HOST',
        help=_('get the signed certificate from the server'))
    parser.add_argument(
        '--cert-path', type=str, dest='path_to_cert', metavar = 'PATH',
        help=_('path to the cert and key files'))
    parser.add_argument(
        '--list-pid', action='store_true', default=False,
        dest='list_pid', help=_("view the list of running processes"))
    parser.add_argument(
        '-d', '--dump',  action='store_true', default=False, dest = 'dump',
        help=_('dump (to be used with option --list-pid)'))
    parser.add_argument(
        '--pid-result',  type=int, metavar = 'PID',
        dest='pid_res', help=_("view the result of the process"))
    parser.add_argument(
        '--pid-kill',  type=int, metavar = 'PID',
        dest='pid_kill', help=_("kill the selected process"))
    parser.add_argument(
        '--session-clean', action='store_true', default=False,
        dest='session_clean', help=_('clear the session cache'))
    parser.add_argument(
        '--session-info', action='store_true', default=False,
        dest='session_info', help=_("view the session information"))
    parser.add_argument(
        '--session-num-info',  type=int, metavar = 'SID',
        dest='session_num_info',
        help=_("view information about session = SID"))
    parser.add_argument(
        '--session-list', action='store_true', default=False,
        dest='session_list',
        help=_("view the active server sessions"))
    parser.add_argument(
        '--update-crl', action='store_true', default=False,
        dest='update_crl', help=_("update the revocation list"))
    parser.add_argument(
        '--stop-consoled', action='store_true', default=False,
        dest='stop_consoled', help=_("stop cl-consoled"))
    parser.add_argument(
        '--no-progress', action='store_true', default=False,
        dest = 'no_progress', help=_('do not display the progress bar'))
    parser.add_argument(
        '-f', '--force', action='store_true', default=False,
        dest = 'no_questions', help=_('silent during the process'))
    parser.add_argument(
        '-P', action='store_true', default=False,
        dest = 'stdin_passwd',
        help=_("use passwords from standard input for users accounts"))
    return parser

def get_view(client, method, sid, view_params):
    try:
        view = client.service[0][method + '_view'](client.sid, view_params)
    except urllib2.URLError, e:
        _print (_('Failed to connect')+':', e)
        raise Exception(1)
    return view

def call_method(client, args, unknown_args, wait_thread):
    method = args.method
    no_questions = args.no_questions
    stdin_passwd = args.stdin_passwd
    view_params = get_view_params(client, method + '_view', step = None, \
                                  expert = True)

    view = get_view(client, method, client.sid, view_params)
    method_parser = get_method_argparser(view, args)
    param_object = _create_obj(client, method)
    try:
        args, unknown_args = method_parser.parse_known_args(unknown_args)
    except SystemExit:
        raise Exception(1)
    for i in unknown_args:
        if i.startswith('-'):
            if i in parse().parse_known_args()[1]:
                wait_thread.stop()
                sys.stdout.write('\r')
                sys.stdout.flush()
                _print (_('Unknown parameter'), i)
                raise Exception(1)
    if not view.groups is None:
        param_object, steps = collect_object(client, param_object, view, args,
                                             wait_thread,stdin_passwd=stdin_passwd)
        if steps.label and hasattr (param_object, 'CheckOnly'):
            param_object['CheckOnly'] = True
            check_res = {}
            while True:
                method_result = client.service[0][method](client.sid,param_object)
                if not method_result:
                    print _('Method not available')
                    return None
                if method_result.ReturnedMessage[0].type and \
                                 method_result.ReturnedMessage[0].type != "pid":
                    wait_thread.stop()

                    check_res = check_result_msg(method_result, view, check_res)
                    if not check_res:
                        return None
                    else:
                        param_object = get_param_pwd(check_res, view,
                                                     param_object, client)
                else:
                    break

            view_params = get_view_params(client, method + '_view', step = None, \
                                      expert = True, brief = True)
            view = get_view(client, method, client.sid, view_params)
            wait_thread.stop()
            sys.stdout.write('\r')
            sys.stdout.flush()
            print_brief(view, steps.label)
            if not no_questions:
                while True:
                    try:
                        ask = raw_input('\n' + _('Run the process? (yes/no): '))
                        red = '\033[31m * \033[0m'
                    except KeyboardInterrupt:
                        ask = 'no'
                        red = '\n'+'\033[31m * \033[0m'
                    if ask.lower() in ['n', 'no']:
                        print red + _("Manually interrupted")
                        return None
                    if ask.lower() in ['y', 'yes']:
                        break

            param_object['CheckOnly'] = False
    else:
        param_object = {}
    method_result = client.service[0][method](client.sid, param_object)
    if not method_result:
        print _('Method not available')
        return None
    if method_result.ReturnedMessage[0].type and \
                     method_result.ReturnedMessage[0].type != "pid":
        for error in method_result.ReturnedMessage:
            params_text = ''
            for Group in view.groups.GroupField:
                for field in Group.fields.Field:
                    if field.name == error.field:
                        params_text += getErrorOnParam(args,field)
            red = '\033[31m * \033[0m'
            _print ('\r' + red + params_text + error.message)
        return None
    wait_thread.stop()
    return method_result
