###################################################################################################################### 
#  Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.                                           # 
#                                                                                                                    # 
#  Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except in compliance     # 
#  with the License. A copy of the License is located at                                                             # 
#                                                                                                                    # 
#      http://www.apache.org/licenses/                                                                               # 
#                                                                                                                    # 
#  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 services.ec2_service
from handlers import EC2_EVENT_SOURCE
from handlers.event_handler_base import *
from handlers.event_handler_base import EventHandlerBase

ERR_EC2_STATE_EVENT = "Error testing Ec2State event {}"

EC2_STATE_EVENT_TITLE = "EC2 state events"
EC2_STATE_NOTIFICATION = "EC2 Instance State-change Notification"
EC2_EVENT_STATE_PARAM = "Ec2State{}"
EC2_STATE_SCOPE_PARAM = "Ec2State{}Scope"

EVENT_DESCRIPTION_STARTED = "Run task when EC2 instance is started"
EVENT_DESCRIPTION_STOPPED = "Run task when EC2 instance is stopped"
EVENT_DESCRIPTION_TERMINATED = "Run task when EC2 instance is terminated"
EVENT_LABEL_STARTED = "Instance started"
EVENT_LABEL_STOPPED = "Instance stopped"
EVENT_LABEL_TERMINATED = "Instance terminated"

EC2_STATE_RUNNING = "running"
EC2_STATE_STOPPED = "stopped"
EC2_STATE_TERMINATED = "terminated"

# scope for reacting to EC2_State events
EC2_EVENT_STATE_SCOPE = "Ec2ventStateScope"
EC2_EVENT_STATE_SCOPE_RESOURCE = "Resource"
EC2_EVENT_STATE_SCOPE_REGION = "Region"

HANDLED_EVENTS = {
    EVENT_SOURCE_TITLE: EC2_STATE_EVENT_TITLE,
    EVENT_SOURCE: handlers.EC2_EVENT_SOURCE,
    EVENT_PARAMETER: EC2_EVENT_STATE_PARAM,
    EVENT_SCOPE_PARAMETER: EC2_STATE_SCOPE_PARAM,
    EVENT_EVENTS: {
        EC2_STATE_RUNNING: {
            EVENT_LABEL: EVENT_LABEL_STARTED,
            EVENT_DESCRIPTION: EVENT_DESCRIPTION_STARTED},
        EC2_STATE_STOPPED: {
            EVENT_LABEL: EVENT_LABEL_STOPPED,
            EVENT_DESCRIPTION: EVENT_DESCRIPTION_STOPPED},
        EC2_STATE_TERMINATED: {
            EVENT_LABEL: EVENT_LABEL_TERMINATED,
            EVENT_DESCRIPTION: EVENT_DESCRIPTION_TERMINATED}
    }
}


class Ec2StateEventHandler(EventHandlerBase):
    def __init__(self, event, context):
        EventHandlerBase.__init__(self, event=event,
                                  context=context,
                                  resource=services.ec2_service.INSTANCES,
                                  handled_event_source=EC2_EVENT_SOURCE,
                                  handled_event_detail_type=EC2_STATE_NOTIFICATION,
                                  event_name_in_detail="state")

    @staticmethod
    def is_handling_event(event, logger):
        try:
            return event.get("source", "") == EC2_EVENT_SOURCE and \
                   event.get("detail-type") == EC2_STATE_NOTIFICATION
        except Exception as ex:
            logger.error(ERR_EC2_STATE_EVENT, ex)
            return False

    def _resource_ids(self):
        return [r.split("/")[-1] for r in self._event.get("resources")]

    def _select_parameters(self, event_name, task):

        params = {}

        # no specific instance the service of the task is not ec2, this allows rds service tasks to be triggered by ec2 events
        if task[handlers.TASK_SERVICE] != "ec2":
            return params

        # if the scope is regional then no specific is but all instances in the region
        if task.get(handlers.TASK_EVENT_SCOPES, {}).get(EC2_EVENT_SOURCE, {}).get(EC2_STATE_NOTIFICATION, {}).get(
                event_name, "") == handlers.EVENT_SCOPE_REGION:
            return params

        # just the source instance of the event
        params["InstanceIds"] = self._resource_ids()

        return params

    def _source_resource_tags(self, session, task):
        ec2 = get_client_with_retries("ec2", methods=["DescribeTags"], context=self._context, region=self._event_region(),
                                      session=session, logger=self._logger)

        resp = ec2.describe_tags_with_retries(Filters=[{"Name": "resource-id", "Values": self._resource_ids()}])
        return {t["Key"]: t["Value"] for t in resp.get("Tags", [])}
