# encoding: utf-8

from ctyun.auth.authsigner import SignV2Auth, SignV4Auth
from ctyun.http.util import HttpClient
from ctyun.cloudtrail.model.request import CreateTrailRequest
from ctyun.cloudtrail.model.result import CreateTrailResult

from ctyun.cloudtrail.model.request import DeleteTrailRequest
from ctyun.cloudtrail.model.result import DeleteTrailResult

from ctyun.cloudtrail.model.request import DescribeTrailsRequest
from ctyun.cloudtrail.model.result import DescribeTrailsResult

from ctyun.cloudtrail.model.request import GetTrailStatusRequest
from ctyun.cloudtrail.model.result import GetTrailStatusResult

from ctyun.cloudtrail.model.request import PutEventSelectorsRequest
from ctyun.cloudtrail.model.result import PutEventSelectorsResult

from ctyun.cloudtrail.model.request import GetEventSelectorsRequest
from ctyun.cloudtrail.model.result import GetEventSelectorsResult

from ctyun.cloudtrail.model.request import UpdateTrailRequest
from ctyun.cloudtrail.model.result import UpdateTrailResult

from ctyun.cloudtrail.model.request import StartLoggingRequest
from ctyun.cloudtrail.model.result import StartLoggingResult

from ctyun.cloudtrail.model.request import StopLoggingRequest
from ctyun.cloudtrail.model.result import StopLoggingResult

from ctyun.cloudtrail.model.request import LookupEventsRequest
from ctyun.cloudtrail.model.result import LookupEventsResult
from oos.DomainConfig import *
from ooscore.exceptions import CallMethodError

SERVICE_NAME = "cloudtrail"  # service name
USE_SSL = True


class TrailClient(object):
    endpoint = ""

    def __init__(self, credentials, client_config, endpoint, sign_payload=False):
        self._credentials = credentials
        self._client_config = client_config
        self.endpoint = endpoint
        self.sign_payload = sign_payload

    def get_user_agent(self):
        return 'ctyun-oos-python-sdk/6.5.7'

    def create_trail(self, req) -> CreateTrailResult:
        """
        :type req CreateTrailRequest
        :param req
        :return: CreateTrailResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='create_trail', endpoint_url=self.endpoint)
        result = CreateTrailResult()
        result = self.invoke(req, "CreateTrail", result)
        return result

    def delete_trail(self, req) -> DeleteTrailResult:
        """
        :type req DeleteTrailRequest
        :param req
        :return: DeleteTrailResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='delete_trail', endpoint_url=self.endpoint)
        result = DeleteTrailResult()
        result = self.invoke(req, "DeleteTrail", result)
        return result

    def describe_trail(self, req) -> DescribeTrailsResult:
        """
        :type req DescribeTrailsRequest
        :param req
        :return: DescribeTrailsResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='describe_trail', endpoint_url=self.endpoint)
        result = DescribeTrailsResult()
        result = self.invoke(req, "DescribeTrails", result)
        return result

    def get_trail_status(self, req) -> GetTrailStatusResult:
        """
        :type req GetTrailStatusRequest
        :param req
        :return: GetTrailStatusResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='get_trail_status', endpoint_url=self.endpoint)
        result = GetTrailStatusResult()
        result = self.invoke(req, "GetTrailStatus", result)
        return result

    def put_event_selectors(self, req) -> PutEventSelectorsResult:
        """
        :type req PutEventSelectorsRequest
        :param req
        :return: PutEventSelectorsResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='put_event_selectors', endpoint_url=self.endpoint)
        result = PutEventSelectorsResult()
        # req.check_req()
        result = self.invoke(req, "PutEventSelectors", result)
        return result

    def get_event_selectors(self, req) -> GetEventSelectorsResult:
        """
        :type req GetEventSelectorsRequest
        :param req
        :return: GetEventSelectorsResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='get_event_selectors', endpoint_url=self.endpoint)

        result = GetEventSelectorsResult()
        result = self.invoke(req, "GetEventSelectors", result)
        return result

    def update_trail(self, req) -> UpdateTrailResult:
        """
        :type req UpdateTrailRequest
        :param req
        :return: UpdateTrailResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='update_trail', endpoint_url=self.endpoint)

        result = UpdateTrailResult()
        result = self.invoke(req, "UpdateTrail", result)
        return result

    def start_logging(self, req) -> StartLoggingResult:
        """
        :type req StartLoggingRequest
        :param req
        :return: StartLoggingResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='start_logging', endpoint_url=self.endpoint)

        result = StartLoggingResult()
        result = self.invoke(req, "StartLogging", result)
        return result

    def stop_logging(self, req) -> StopLoggingResult:
        """
        :type req StopLoggingRequest
        :param req
        :return: StopLoggingResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='stop_logging', endpoint_url=self.endpoint)

        result = StopLoggingResult()
        result = self.invoke(req, "StopLogging", result)
        return result

    def lookup_events(self, req):
        """
        :type req LookupEventsRequest
        :param req
        :return: LookupEventsResult
        """
        domain = DomainConfig()
        if domain.is_s5_endpoint(self.endpoint):
            raise CallMethodError(call_method='lookup_events', endpoint_url=self.endpoint)

        result = LookupEventsResult()
        result = self.invoke(req, "LookupEvents", result)

        return result

    def invoke(self, req, action, result):
        # "http://oos-xxx-cloudtrail.ctyunapi.cn:80
        _endpoint = self.endpoint.lower().replace("http://", "").replace("https://", "")

        region_name = _endpoint[4:_endpoint.find("-cloudtrail")]
        if _endpoint.find(":") > 0:
            _endpoint = _endpoint[0: _endpoint.find(":")]

        host = _endpoint
        headers = {
            'Host': host,
            'User-Agent': self.get_user_agent(),
            'Content-Type': 'application/json',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'X-Amz-Target':
                'cn.ctyunapi.oos-cn-cloudtrail.v20131101.CloudTrail_20131101.' + action,
        }

        http_client = HttpClient(
            self.endpoint, data=req.json_string().encode('utf-8'), headers=headers, method="POST")

        if self._client_config.signature_version.lower() == "v2":
            v2auth = SignV2Auth(self._credentials)
            v2auth.add_auth(http_client)
        else:
            v4auth = SignV4Auth(self._credentials, SERVICE_NAME, region_name, http_client, self.sign_payload)
            v4auth.add_auth(http_client)

        result = http_client.request(result, action=action)

        return result
