#!/usr/bin/env python
#==============================================================================
# Copyright 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Amazon Software License (the "License"). You may not use
# this file except in compliance with the License. A copy of the License is
# located at
#
#       http://aws.amazon.com/asl/
#
# or in the "license" file accompanying this file. This file is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or
# implied. See the License for the specific language governing permissions
# and limitations under the License.
#==============================================================================
import locale
import sys
from getpass import getpass

from lib.utility import misc
from scli import prompt
from scli.constants import ParameterSource as Source
from scli.constants import TerminalConstant
from scli.exception import EBSCliException
from scli.resources import TerminalMessage
from scli.resources import TerminalPromptAskingMessage
from scli.resources import TerminalPromptSettingParameterMessage
from scli.parameter import Parameter


class TerminalBase(object):

    
    @classmethod
    def ask_parameter(cls, parameter_pool, parameter_name, 
                       display_value = None, autogen_value = None, no_echo = False):
        value = cls.ask_value(parameter_pool, parameter_name, 
                              display_value, autogen_value, no_echo = no_echo)
        
        if value is None:
            return None
            
        param = Parameter(parameter_name, value, Source.Terminal)
        parameter_pool.put(param, True)
        
        return value

    @classmethod
    def ask_value(cls, parameter_pool, parameter_name, 
                  display_value = None, autogen_value = None, no_echo = False):
        if autogen_value is not None:
            message = TerminalPromptAskingMessage[parameter_name].\
                format(TerminalMessage.AutoGeneratedValue.format(autogen_value))
            answer = cls.line_input(message, True, no_echo = no_echo)
            
            return answer if answer is not None else autogen_value
                        
        elif parameter_pool.has(parameter_name):
            if no_echo:
                value = '******' if display_value is None else display_value
            else:
                original_value = parameter_pool.get_value(parameter_name, False)
                value = original_value if display_value is None else display_value
            message = TerminalPromptAskingMessage[parameter_name].\
                format(TerminalMessage.CurrentValue.format(value))

            return cls.line_input(message, True, no_echo = no_echo)
            
        else:
            message = TerminalPromptAskingMessage[parameter_name].format('')
            return cls.line_input(message, False, no_echo = no_echo)


    @classmethod    
    def line_input(cls, message, can_return_none = False, no_echo = False, trim = True):
        value = ''
        codec = locale.getpreferredencoding()
        
        if no_echo:
            input_method = getpass
        elif sys.version_info > (3, 0):        
            input_method = input
        else:
            input_method = raw_input
        
        while len(value) < 1: 
            if sys.version_info > (3, 0):
                    value = misc.to_unicode(input_method(message), codec)
            else:
                value = misc.to_unicode(input_method(message.encode(codec)), codec)
            if len(value) < 1:
                if can_return_none:
                    return None
        if trim:
            return value.strip()
        else:
            return value

        
    @classmethod    
    def single_choice(cls, choice_list, title = None, 
                       message = None, can_return_none = False):
        if choice_list and not isinstance(choice_list, list):
            raise EBSCliException('Invalid parameter type.')
        
        if message is None:
            message = TerminalMessage.SingleChoice

        if title is not None:
            print(title)
        for index, choice in enumerate(choice_list):
            print('{0}) {1}'.format(index + 1, choice))

        select = -1
        while select not in list(range(1, len(choice_list) + 1)):
            select = cls.line_input('{0} ({1} to {2}): '.format(message, 1, len(choice_list)), True)
            if select is None and can_return_none:
                return None # No input from customer, return None
            try:
                select = int(select)
            except:
                select = -1
            
        return select - 1

            
    @classmethod
    def ask_confirmation(cls, messsage = None, can_return_none = False):
        if messsage is None:
            messsage = TerminalMessage.ConfirmToProceed 
        
        value = cls.line_input(messsage, can_return_none)

        if value is None:
            return None
        elif misc.string_equal_ignore_case(value, TerminalConstant.Y)\
            or misc.string_equal_ignore_case(value, TerminalConstant.Yes):
            return True
        else:
            return False
        
        
    @classmethod
    def _set_parameter_value(cls, parameter_pool, name, value, source, force = False):
        # Set parameter value if not specified as before with higher priority
        if parameter_pool.has(name) \
                and Source.is_ahead(parameter_pool.get_source(name), Source.Terminal):
            value = parameter_pool.get_value(name, False)
        else:
            parameter_pool.put(Parameter(name, value, source), force)
        
        prompt.info(TerminalPromptSettingParameterMessage[name].format(value))        
