#!/usr/bin/env python
# -*- coding: utf-8 -*-
#==============================================================================
# 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.
#==============================================================================
from lib.utility import misc
from scli.constants import CommandType, EbCliVersion, ParameterName
import types

#----------------------------------------------
# Command line arguments
#----------------------------------------------

class BaseMessage(object):
    pass


class EBSCliAttr(object):
    Name = u'AWS Elastic Beanstalk Command Line Interface ' + misc.to_unicode(EbCliVersion)
    Version = u'AWS Elastic Beanstalk Command Line Interface ' + misc.to_unicode(EbCliVersion)
    Usage = u'%(prog)s {COMMAND} [options]'
    ErrorMsg =u'Error: {0}\n{1}Try {2} --help for more information.\n'
    InvalidCommand = u'Invalid command: {0}'
    NotSupportedCommand = u'Not supported command: {0} {1}'

    
""" Define command line argument switch """
CLISwitch = {
    ParameterName.Command : u'command',
    ParameterName.SubCommand : u'sub-commands',
    ParameterName.AwsCredentialFile : u'aws-credential-file',
    ParameterName.AwsAccessKeyId :  u'access-key-id',    
    ParameterName.AwsSecretAccessKey :  u'secret-key',    
    ParameterName.Region :  u'region',    
    ParameterName.ServiceEndpoint :  u'url',
    ParameterName.EnvironmentTier :  u'environment-tier',
    ParameterName.SolutionStack :  u'solution-stack',
    ParameterName.ApplicationName :  u'application-name',    
    ParameterName.ApplicationVersionName :  u'version-label',    
    ParameterName.EnvironmentName :  u'environment-name',    
    ParameterName.WaitForFinishTimeout :  u'polling-timeout',    
    ParameterName.Force : u'force',
    ParameterName.Verbose : u'verbose',
}


""" Define help message for each command line argument """
CLISwitchMsg = {
    ParameterName.Command : u'',    
    ParameterName.AwsCredentialFile : u'File location where your AWS credentials ' \
        'are saved. Use the environment variable AWS_CREDENTIAL_FILE to set the ' \
        'file location.',
    ParameterName.AwsAccessKeyId :  u'Your AWS Access Key ID.',    
    ParameterName.AwsSecretAccessKey :  u'Your AWS Secret Key.',    
    ParameterName.Region : u'AWS Elastic Beanstalk region (i.e., us-east-1).',    
    ParameterName.ServiceEndpoint :  u'AWS Elastic Beanstalk endpoint (i.e., ' \
        'elasticbeanstalk.us-east-1.amazonaws.com).',    
    ParameterName.EnvironmentTier :  u'Environment tier used for the application',
    ParameterName.SolutionStack :  u'Solution stack used as an application ' \
        'container type.',    
    ParameterName.ApplicationName :  u'The name of the application to deploy.',    
    ParameterName.ApplicationVersionName :  u'The name of the application version ' \
        'to deploy.',    
    ParameterName.EnvironmentName : u'A unique name for the environment deployment. ' \
        'The environment name is used in the application URL.',    
    ParameterName.WaitForFinishTimeout :  u'Number of seconds before a start or stop ' \
        'operation times out when polling for environment status. ' \
        'The default is {0} second.',            
    ParameterName.Force : u'Skip confirmation prompt.',
    ParameterName.Verbose : u'Display verbose information.',
}



#----------------------------------------------
# Terminals
#----------------------------------------------

class TerminalMessage(object):
    CurrentValue = u' (current value is "{0}")'
    AutoGeneratedValue = u' (auto-generated value is "{0}")'
    SingleChoice = u'Select'
    AvailableRegion =  u'Available service regions are:'
    AvailableEnvironmentTier = u'Available environment tiers are:'
    AvailableSolutionStack = u'Available solution stacks are:'
    AvailableEnvironmentType = u'Available environment types are:'

    
    ConfirmToProceed = u'Are you sure? [y/n]: '
    
    AWSKeyLocateHelp = u'To get your AWS Access Key ID and Secret Access Key, \n  visit ' \
        '"https://aws-portal.amazon.com/gp/aws/securityCredentials".'
    
    CopyDefaultToBranch = u'Do you want to copy the settings from environment "{0}" for the new branch? [y/n]: '
    NoBranchToRegister = u"The branch doesn't exist."
    FallBackToDefaultBranch = u'The current branch "{0}" is not associated with an Elastic Beanstalk '\
                                 'environment. Call "eb branch" to set up a new environment for this branch. '\
                                 '\nProceeding with default settings.'

""" Define prompt message for terminal interface """
TerminalPromptAskingMessage = {
    ParameterName.AwsAccessKeyId :  u'Enter your AWS Access Key ID{0}: ',    
    ParameterName.AwsSecretAccessKey :  u'Enter your AWS Secret Access Key{0}: ',    
    ParameterName.Region :  u'Select an AWS Elastic Beanstalk service region{0}.',    
    ParameterName.ServiceEndpoint :  u'Enter AWS Elastic Beanstalk service endpoint{0}: ',
    ParameterName.EnvironmentTier :  u'Select an environment tier{0}.',
    ParameterName.SolutionStack :  u'Select a solution stack{0}.',    
    ParameterName.ApplicationName :  u'Enter an AWS Elastic Beanstalk application name{0}: ',    
    ParameterName.ApplicationVersionName :  u'Enter an AWS Elastic Beanstalk application version name{0}: ',    
    ParameterName.EnvironmentName :  u'Enter an AWS Elastic Beanstalk environment name{0}: ',
    
    ParameterName.RdsEnabled : u'Create an RDS DB Instance? [y/n]{0}: ',
    ParameterName.RdsSourceSnapshotName : u'Enter your snapshot ID: ',
    ParameterName.RdsMasterPassword : u'Enter an RDS DB master password{0}: ',
    ParameterName.RdsDeletionPolicy: u'If you terminate your environment, your RDS DB '\
        'Instance will be deleted and you will lose your data.\nCreate snapshot? [y/n]{0}: ',
    ParameterName.InstanceProfileName: u'Enter the name or ARN of an existing instance profile: ',    
    ParameterName.EnvironmentType: u'Select an environment type{0}.',    
}


TerminalPromptSettingParameterMessage = {
    ParameterName.EnvironmentName : u'Using auto-generated AWS Elastic Beanstalk environment name: "{0}".',
    ParameterName.Region :  u'Setting AWS Elastic Beanstalk region to "{0}".',
    ParameterName.ServiceEndpoint :  u'Setting AWS Elastic Beanstalk service endpoint to "{0}".',
    ParameterName.RdsEndpoint :  u'Setting AWS Relational Database Service endpoint to "{0}".',
    ParameterName.EnvironmentTier :  u'Setting environment tier to "{0}".',
    ParameterName.SolutionStack : u'Setting solution stack to "{0}".',
    ParameterName.RdsSnippetUrl : u'Setting RDS extension url to "{0}".',    
    ParameterName.CurrentBranch : u'The current branch is "{0}".',
}


TerminalPromptUsingParameterMessage = {
    ParameterName.AwsAccessKeyId :  u'AWS Access Key ID: ***',    
    ParameterName.AwsSecretAccessKey :  u'AWS Secret Access Key: ***',    
    ParameterName.Region :  u'AWS Elastic Beanstalk service region: {0}.',    
    ParameterName.ServiceEndpoint :  u'AWS Elastic Beanstalk service endpoint: {0}.',
    ParameterName.EnvironmentTier :  u'Environment tier {0}.',
    ParameterName.SolutionStack :  u'Solution stack {0}.',
    ParameterName.ApplicationName :  u'AWS Elastic Beanstalk application: {0}.',    
    ParameterName.ApplicationVersionName :  u'AWS Elastic Beanstalk application version : {0}.',   
    ParameterName.EnvironmentName :  u'AWS Elastic Beanstalk environment: {0}.',    
}


class RdsTerminalMessage(object):
    RdsSnapshotNameSelect = u'Create an RDS BD Instance from{0}:'
    NoSnapshot = u'[No snapshot]'
    OtherSnapshot = u'[Other snapshot]'
    
    PasswordConfirmation = u'Retype password to confirm: '
    PasswordNotMatch = u'Error: passwords do not match.'
    PasswordMatchFailure = u'Rerun "eb init" to set up configuration.'
    PasswordWrongFormat = u'Error: password must contain from 8 to 41 characters and must not contain backslashes, forward slashes, or @ symbols.'

class IamTerminalMessage(object):
    ProfileNameSelect = u'Attach an instance profile{0}:'
    CreateProfile = u'[Create a default instance profile]'
    NoProfile = u'[No instance profile]'
    OtherProfile = u'[Other instance profile]'
    ProfileNotExist = u'Instance profile {0} does not exist.'
    AccessDeniedMessage = u'You IAM user does not have sufficient permission. {0}'
    ContinueWithoutRole = u'Do you want to proceed without attaching an instance profile? [y/n]: '
    
#----------------------------------------------
# Operation
#----------------------------------------------

class BaseOpMessage(object):
    WaitForEnv = u'Waiting for environment "{0}" to {1}.'
    EnvNotExist = u'Environment "{0}" does not exist.'
    Running = u'Running.'
    UserCanInterrupt = u'Press Ctrl+C to stop polling. The operation will continue on the server side.'


class CreateApplicationOpMessage(object):
    Start = u'Now creating application "{0}".'
    AlreadyExist = u'Starting application "{0}".'
    Succeed = u'Created application "{0}".'


class DeleteApplicationOpMessage(object):
    Start = u'Now deleting application "{0}".'
    AlreadyDelete = u'Application "{0}" has already been deleted.'
    Succeed = u'Deleted application "{0}".'


class DescribeEnvironmentOpMessage(object):
    Start = u'Retrieving status of environment "{0}".'
    NoEnvironment = u'Environment "{0}" is not running.'
    
    def format_result(self, *args):
        # Don't display URL if cname is null
        if args[0]:
            return u'URL\t\t: {0}\nStatus\t\t: {1}\nHealth\t\t: {2}'.format(*args)
        else:
            return u'Status\t\t: {0}\nHealth\t\t: {1}'.format(*args[1:])
    Result = BaseMessage()
    Result.format = types.MethodType(format_result, Result)
    
    def format_detail(self, *args):
        # Don't display tier if it is null
        if args[2]:
            return u'Environment Name: {0}\nEnvironment ID\t: {1}\nEnvironment Tier: {2}\nSolution Stack\t: {3}\n'\
        'Version Label\t: {4}\nDate Created\t: {5}\nDate Updated\t: {6}\nDescription\t: {7}'.format(*args)
        else:
            new_args = list(args)
            del(new_args[2])
            return u'Environment Name: {0}\nEnvironment ID\t: {1}\nSolution Stack\t: {2}\n'\
        'Version Label\t: {3}\nDate Created\t: {4}\nDate Updated\t: {5}\nDescription\t: {6}'.format(*new_args)
    Detail = BaseMessage()
    Detail.format = types.MethodType(format_detail, Detail)
    
    RdsInfo = u'\nRDS Database: {0} | {1}:{2}'
    RdsDetail = u'Database Engine:\t{0}\nAllocated Storage:\t{1}\nInstance Class:\t\t{2}\n'\
        'Multi AZ:\t\t{3}\nMaster Username:\t{4}\nCreation Time:\t\t{5}\n'\
        'DB Instance Status:\t{6}'
    QueueInfo = u'{0}\t: {1}'


class CreateEnvironmentOpMessage(object):
    Start = u'Now creating Environment "{0}".'
    AlreadyExist = u'Environment "{0}" already exists. Skipped creating.'
    UsingOptionSetting = u'Using option settings retrieved from file "{0}" to create environment.'
    Succeed = u'Started creating environment.'
    WaitAfterLaunch = u'Waiting for environment "{0}" to launch.'


class WaitForCreateEnvironmentFinishOpMessage(object):
    Action = u'launch'
    Succeed = u'Creation of environment "{0}" has completed.'
    Timeout = u'Timeout for waiting Environment {0} finishing launch.'
    
    def format_result(self, *args):
        if args[0]:
            return u'Application is available at "{0}".'.format(*args)
        else:
            return u'Application is available.'.format(*args[1:])
    Result = BaseMessage()
    Result.format = types.MethodType(format_result, Result)
    
class TerminateEnvironmentOpMessage(object):
    Start = u'Now terminating environment "{0}".'
    Succeed = u'Stopping environment "{0}". This may take a few minutes.'    


class WaitForTerminateEnvironmentFinishOpMessage(object):
    Action = u'stop'
    Succeed = u'Stop of environment "{0}" has completed.' 
    Timeout = u'Timeout for waiting Environment "{0}" finishing termination.'
    Status = u'Environment Status is "{0}". Health is "{1}".'
    Result = u'Environment status is: "{0}".'


class UpdateEnvironmentOptionSettingOpMessage(object):
    Continue = u'Continue? [y/n]: '
    Start = u'Now updating environment "{0}"\'s option settings.'
    UsingOptionSetting = u'Using option settings retrieved from file "{0}" to update environment.'
    Succeed = u'Updating environment "{0}". This may take a few minutes.'    


class WaitForUpdateEnvOptionSettingFinishOpMessage(object):
    Action = u'updating'
    Succeed = u'Update of environment "{0}" has completed.' 
    Timeout = u'Timeout for waiting Environment "{0}" finishing update.'
    
    Result = BaseMessage()
    def format_result(self, *args):
        if args[0]:
            return u'Environment URL is "{0}", status is: "{1}", health is "{2}".'.format(*args)
        else:
            return u'Environment status is: "{0}", health is "{1}".'.format(*args[1:])
    Result.format = types.MethodType(format_result, Result)
    
class EnvRetrieveInfoOpMessage(object):
    Action = u'generating logs'
    Timeout = u'Timeout for waiting Environment "{0}" generating log.'
    FileOuputPrefix = u'==================== {0} ===================='
    LineOuputMask = u'[{0}] {1}'
    
    
class CreateApplicationVersionOpMessage(object):
    Start = u'Now creating application version "{0}" using the sample application.'
    AlreadyExist = u'Application version "{0}" already exists. Skipped creating.'
    HasDefaultAppSource = u'Specified solution stack "{0}" has default application.'
    CannotRecognize = u'Cannot infer sample app for solution stack "{0}".'
    Skip = u'Skipped creating sample application version.'
    Succeed = u'Created application version "{0}".'    

class PushApplicationVersionOpMessage(object):
    EnvNotExist = u'Environment {0} is not running.'

class RecordApplicationVersionOpMessage(object):
    Start = u'Recording application version of environment "{0}".'
    NotExist = u'Cannot find environment "{0}".'
    Succeed = u'Recorded application version "{0}".'  
    
class ListSolutionStackOpMessage(object):
    Start = u'Retrieving available solution stacks.'
    Result = u'Available solution stacks: "{0}"'

class SaveConfigurationSettingOpMessage(object):
    Start = u'Now retrieving options settings for environment "{0}".'
    Succeed = u'Saved option settings in "{0}"'
        
class WriteAwsCredentialFileOpMessage(object):
    Confirm = u'Confirm to create AWS Credential file "{0}"? [y/n]'
    Succeed = u'Updated AWS Credential file at "{0}".'    
            
class AskConfirmationOpMessage(object):
    CommandConfirmation ={
        CommandType.STOP : u'Terminate environment? [y/n]: ',
        CommandType.DELETE : u'Delete application? [y/n]: ',
        CommandType.UPDATE : u'Update environment? [y/n]: ',
    }    
    
    CommandWarning ={
        CommandType.STOP : u'If you terminate your environment, your RDS DB Instance will be'\
            ' deleted and you will lose your data.',
        CommandType.DELETE : u'If you delete your application, your RDS DB Instance will be'\
            ' deleted and you will lose your data.',
        CommandType.UPDATE : u'If you udpate your environment, your RDS DB Instance will be'\
            ' deleted and you will lose your data.',
    }

class GetEnvironmentEventsOpMessage():
    NotValidNumber = u'"{0}" is not a valid number.'

        
#----------------------------------------------
# Validation
#----------------------------------------------


class ValidationMessage(object):
    EmptyString = u"{0}'s value cannot be empty."
    InvalidNumber = u'Invalid number "{0}"'
    NumberTooBig = u'{0} is bigger than allowed range'
    NumberTooSmall = u'{0} is smaller than allowed range"'
    
    InvalidSolutionStack = u'Specified solution stack "{0}" is invalid.'
    InvalidRegion = u'Specified region "{0}" is invalid.'
    
    ValidateSettingError = u'{0}: Namespace "{1}", Option name "{2}"\n    {3}'

    EnvTypeInapplicable = u'The {0} environment type is not applicable to your environment.'
    EnvTypeBlowAwayOptionSettings = u'Some of your option settings are ignored because they don\'t apply to your environment type.'
    
    
#----------------------------------------------
# Configuration file
#----------------------------------------------

class GeneralFileMessage(object):
    RenameFile = u'Renamed file "{0}" to "{1}".'
    RotationNameNotAvailable = u'File {0} cannot be rotated because no rotation name is available.'


class CredentialFileMessage(object):
    CannotFind = u'The AWS credential file, "{0}", cannot be found. Use the "{1}" command to create it.'
    CorrectionSuggestion = u'The AWS credential, "{0}", could not be parsed. ' \
        'Delete the file, or try the {1} command to recreate.'    
            
class CredentialFileErrorMessage(object):
    ReadError = u'Encountered error while reading from file {0}.'   
    WriteError = u'Encountered error while writing file {0}.'


    
class ConfigFileMessage(object):
    CannotFind = u'The configuration file, "{0}", cannot be found. Use the "{1}" command to create it.'
    CorrectionSuggestion = u'The configuration file, "{0}", could not be parsed. '\
        'Delete the file, or try the "{1}" command to reconfigure.'    
    BranchResetWarning = u'Existing branches have been reset due to a change in the application name, '\
        'region, or solution stack.'
    
class ConfigFileErrorMessage(object):
    ReadError = u'Encountered error while reading from file {0}.'   
    WriteError = u'Encountered error while saving file {0}.'
    PermissionError = u'Warning. File "{0}" has incorrect access permission '\
         'and can be accessed by other users.'
    

class DevToolsMessage(object):
    GitCommandError = u'Unable to call Git. Install Git to deploy to Elastic Beanstalk. {0}'
    GitRepoNotExist = u'{0}\nWarning: Your directory has not been initialized as a Git repository. '\
        'To create a local Git repository, run "git init" and then re-run the "eb init" command.'
    InitError = u'Failed to update local Git repository setting. {0}'
    ExecutionError = u'Failed to update local Git configuration. '\
        'Follow the instructions at "{0}" to set up your Git repository, and then try again.'
    FileMissingError = u'Cannot run AWS Dev Tools initialization script at "{0}".'    
    GitHeadNotExist = u'Unable to retrieve HEAD of local repository. {0}'    
    PushLocalHead = u'Would you like to deploy the latest Git commit to your environment? [y/n]: '
    PushFail = u'Cannot run aws.push for local repository HEAD: {0}'    
    
class OptionSettingFileMessage(object):
    CannotFind = u'The option setting file, "{0}", cannot be found. Use the "{1}" command to create it.'
    CorrectionSuggestion = u'The option setting, "{0}", could not be parsed. ' \
        'Delete the file, or try the {1} command to recreate.'    
    
class OptionSettingFileErrorMessage(object):
    ReadError = u'Encountered error while reading from file {0}.'   
    WriteError = u'Encountered error while saving file {0}.'
