"""
This code is modified from the sample code blueprint called
alexa-skills-kit-color-expert-python
"""

import http.client
import json

CLIENT_ID = "<enter IRAS API App client ID>"
SECRET = "<enter IRAS API App client secret>"
API_URL = "apiservices.iras.gov.sg"

# --------------- Helpers that build all of the responses ----------------------

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'SSML',
            'ssml': output
        },
        'card': {
            'type': 'Simple',
            'title': "SessionSpeechlet - " + title,
            'content': "SessionSpeechlet - " + output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }


def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

def build_speech_text(reply_or_reprompt, clear_or_unclear, locale='en-US'):
    
    dic =   {'reply':   { 'clear':  { 'en-US': "<speak>The buyer stamp duty for %s dollars on %s is. %s.</speak>" 
                                    , 'ja-JP': "<speak><say-as interpret-as='interjection'>あのう.</say-as> %sドルの%sの印紙税は. %sです.</speak>"
                                    }
                        , 'unclear':{ 'en-US': "I'm not sure what your question is. Please try again."
                                    , 'ja-JP': "<speak>わかりません. もう一度お試しください.</speak>"
                                    }
                        }
            ,'reprompt': { 'clear': { 'en-US': "You can ask me about buyer stamp duty by saying, buyer stamp duty for 500000 on 26 October 2016."
                                    , 'ja-JP': "あなたは私に'昨日の500000の印紙税はいくらですか'尋ねることができます."
                                    }
                        , 'unclear':{ 'en-US': "I'm not sure what your question is. You can ask me about buyer stamp duty by saying, buyer stamp duty for 500000 on 26 October 2016."
                                    , 'ja-JP': "わかりません. もう一度お試しください."
                                    }
                        }
            }

    if reply_or_reprompt in dic and clear_or_unclear in dic[reply_or_reprompt] \
            and locale in dic[reply_or_reprompt][clear_or_unclear]:
        return dic[reply_or_reprompt][clear_or_unclear][locale]
    else:
        return None



# --------------- Functions that control the skill's behavior ------------------

def get_welcome_response(request):
    """ If we wanted to initialize the session to have some attributes we could
    add those here
    """

    session_attributes = {}
    card_title = "Welcome"
    speech_output = "<speak>Hello. You can ask me about buyer stamp duty by saying, " \
                    "buyer stamp duty for 500000 on 26 October 2016.</speak>"
    # If the user either does not reply to the welcome message or says something
    # that is not understood, they will be prompted again with this text.
    reprompt_text = "You can ask me about buyer stamp duty by saying, " \
                    "buyer stamp duty for 500000 on 26 October 2016."
                    
    should_end_session = False

    if request and request['locale'] == "ja-JP":
        speech_output = "<speak><say-as interpret-as='interjection'>こんにちは.</say-as> あなたは私に'昨日の500000の印紙税はいくらですか'尋ねることができます.</speak>"
        reprompt_text = "もう一度お試しください"
    
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))


def handle_session_end_request(request):
    card_title = "Session Ended"
    
    speech_output = "<speak>Good bye, and remember to pay your tax on time!</speak>"

    if request and request['locale'] == "ja-JP":
        speech_output = "<speak><say-as interpret-as='interjection'>じゃね.</say-as></speak>"

    # Setting this to true ends the session and exits the skill.
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))


def calculate_bsd(intent_request, session):
    """ Sets the color in the session and prepares the speech to reply to the
    user.
    """

    intent = intent_request['intent']
    locale = intent_request['locale']
    
    card_title = intent['name']
    session_attributes = {}
    should_end_session = False

    bsd = None
    if 'value' in intent['slots'] and 'date' in intent['slots']:
        value = intent['slots']['value']['value']
        date = intent['slots']['date']['value']
        
        # Call IRAS API to calculate buyer stamp duty
        result = get_bsd(value, date)
        if result != "error" and result['returnCode'] == 10:
            bsd = result['data']

    if bsd:
        speech_output = build_speech_text('reply', 'clear', locale) % (value, date, str(bsd))
        reprompt_text = build_speech_text('reprompt', 'clear', locale)
    else:
        speech_output = build_speech_text('reply', 'unclear', locale)
        reprompt_text = build_speech_text('reprompt', 'unclear', locale)

    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

# --------------- Functions that interact with IRAS API ------------------

def get_bsd(value, date):
    conn = http.client.HTTPSConnection(API_URL)
    headers = {
        'x-ibm-client-id': CLIENT_ID,
        'x-ibm-client-secret': SECRET,
        'content-type': "application/json",
        'accept': "application/json"
        }
    payload = "{\"client_id\":\"%s\",\"value\":%s,\"documentDate\":\"%s\"}" % (CLIENT_ID, value, date)
    result = None

    conn.request("POST", "/iras/prod/SD/CalPropertyBSD", payload, headers)
    try:
        res = conn.getresponse()
        result = json.loads(res.read().decode('utf-8'))
    except Exception as err:
        result = err
    finally:
        conn.close
    
    return result

# --------------- Events ------------------

def on_session_started(session_started_request, session):
    """ Called when the session starts """

    print("on_session_started requestId=" + session_started_request['requestId']
          + ", sessionId=" + session['sessionId'])


def on_launch(launch_request, session):
    """ Called when the user launches the skill without specifying what they
    want
    """

    print("on_launch requestId=" + launch_request['requestId'] +
          ", sessionId=" + session['sessionId'])
    # Dispatch to your skill's launch
    return get_welcome_response(launch_request)


def on_intent(intent_request, session):
    """ Called when the user specifies an intent for this skill """

    print("on_intent requestId=" + intent_request['requestId'] +
          ", sessionId=" + session['sessionId'])

    intent = intent_request['intent']
    intent_name = intent_request['intent']['name']

    # Dispatch to your skill's intent handlers
    if intent_name == "BSDIntent":
        return calculate_bsd(intent_request, session)
    elif intent_name == "AMAZON.HelpIntent":
        return get_welcome_response(intent_request)
    elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        return handle_session_end_request(intent_request)
    else:
        raise ValueError("Invalid intent")


def on_session_ended(session_ended_request, session):
    """ Called when the user ends the session.

    Is not called when the skill returns should_end_session=true
    """
    print("on_session_ended requestId=" + session_ended_request['requestId'] +
          ", sessionId=" + session['sessionId'])
    # add cleanup logic here


# --------------- Main handler ------------------

def lambda_handler(event, context):
    """ Route the incoming request based on type (LaunchRequest, IntentRequest,
    etc.) The JSON body of the request is provided in the event parameter.
    """
    print("event.session.application.applicationId=" +
          event['session']['application']['applicationId'])

    """
    Uncomment this if statement and populate with your skill's application ID to
    prevent someone else from configuring a skill that sends requests to this
    function.
    """
    if event['session']['application']['applicationId'] != \
            "amzn1.ask.skill.7cc54f8f-7a7a-42fb-8433-5a117c0c7cc0":
        raise ValueError("Invalid Application ID")

    if event['session']['new']:
        on_session_started({'requestId': event['request']['requestId']},
                           event['session'])

    if event['request']['type'] == "LaunchRequest":
        return on_launch(event['request'], event['session'])
    elif event['request']['type'] == "IntentRequest":
        return on_intent(event['request'], event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])
