"""
"Copyright 2023 ClearBlade Inc."

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2023 ClearBlade Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

from .config_manager import ClearBladeConfigManager
from .http_client import AsyncClient, SyncClient
from .pagers import ListDeviceRegistriesAsyncPager, ListDeviceRegistryPager
from .registry_types import *


class ClearBladeRegistryManager():
    def __init__(self) -> None:
        self._cb_config = ClearBladeConfigManager()

    def _create_registry_body(self, registry: DeviceRegistry) :
        registry_json = {'id':registry.id}
        if registry.credentials:
            registry_json['credentials']=registry.credentials
        if registry.http_config:
            registry_json['httpConfig']=registry.http_config
        if registry.mqtt_config:
            registry_json['mqttConfig']=registry.mqtt_config
        if registry.state_notification_config:
            registry_json['stateNotificationConfig']=registry.state_notification_config
        if registry.event_notification_configs:
            registry_json['eventNotificationConfigs']=registry.event_notification_configs
        if registry.log_level:
            registry_json['logLevel']=registry.log_level
        return registry_json

    def _prepare_params_for_registry_list(self, request:ListDeviceRegistriesRequest):
        request_params = {'parent':request.parent}
        if request.page_size:
            request_params['page_size'] = request.page_size
        if request.page_token:
            request_params['page_token'] = request.page_token
        return request_params

    def create(self,
        request: CreateDeviceRegistryRequest = None)->DeviceRegistry:
        body = self._create_registry_body(request.device_registry)
        params = {'parent':request.parent}
        sync_client = SyncClient(clearblade_config=self._cb_config.admin_config)
        response = sync_client.post(api_name = "cloudiot",request_body=body,request_params=params)
        return DeviceRegistry.from_json(response.json())

    async def create_async(self,
        request: CreateDeviceRegistryRequest = None)->DeviceRegistry:
        body = self._create_registry_body(request.device_registry)
        params = {'parent':request.parent}
        async_client = AsyncClient(clearblade_config=self._cb_config.admin_config)
        response = await async_client.post(api_name = "cloudiot",request_body=body,request_params=params)
        return DeviceRegistry.from_json(response.json())

    def get(self,
            request: GetDeviceRegistryRequest = None):
        if request.name == None:
            raise Exception('Registry Path is not present in the request')

        clearblade_config = self._cb_config.regional_config(request.name)

        sync_client = SyncClient(clearblade_config=clearblade_config)
        response = sync_client.get(api_name = "cloudiot")
        return DeviceRegistry.from_json(response.json())

    async def get_async(self,
                        request: GetDeviceRegistryRequest = None):
        
        if request.name == None:
            raise Exception('Registry Path is not present in the request')

        clearblade_config=await self._cb_config.regional_config_async(request.name)
        async_client = AsyncClient(clearblade_config=clearblade_config)
        response = await async_client.get(api_name = "cloudiot")
        return DeviceRegistry.from_json(response.json())

    def get_device_registry_list(self, request: ListDeviceRegistriesRequest):
        request_params = self._prepare_params_for_registry_list(request=request)
        sync_client = SyncClient(clearblade_config=self._cb_config.admin_config)
        response = sync_client.get(api_name = "cloudiot",request_params=request_params)

        if response.status_code == 200:
            return ListDeviceRegistriesResponse.from_json(response.json())
        return None

    def list(self,
            request: ListDeviceRegistriesRequest = None):

        list_device_registry_response = self.get_device_registry_list(request=request)
        if list_device_registry_response:
            return ListDeviceRegistryPager(method=self.get_device_registry_list,
                                           request=request,
                                           response=list_device_registry_response)

    async def get_device_registry_list_async(self, request: ListDeviceRegistriesRequest):
        request_params = self._prepare_params_for_registry_list(request=request)
        async_client = AsyncClient(clearblade_config=self._cb_config.admin_config)
        response = await async_client.get(api_name = "cloudiot",request_params=request_params)

        if response.status_code == 200:
            return ListDeviceRegistriesResponse.from_json(response.json())
        return None

    async def list_async(self, request: ListDeviceRegistriesRequest):
        list_device_registry_response = await self.get_device_registry_list_async(request=request)
        if list_device_registry_response:
            return ListDeviceRegistriesAsyncPager(method=self.get_device_registry_list_async,
                                                  request=request,
                                                  response=list_device_registry_response)
        return None

    def delete(self,
            request: DeleteDeviceRegistryRequest = None):
        params = {'name':request.name}
        sync_client = SyncClient(clearblade_config=self._cb_config.admin_config)
        response = sync_client.delete(api_name = "cloudiot",request_params=params)
        return response

    async def delete_async(self,
            request: DeleteDeviceRegistryRequest = None):
        params = {'name':request.name}
        async_client = AsyncClient(clearblade_config=self._cb_config.admin_config)
        response = await async_client.delete(api_name = "cloudiot",request_params=params)
        return response

    def patch(self,
        request: UpdateDeviceRegistryRequest = None)->DeviceRegistry:
        if request.name == None:
            raise Exception('Registry Path is not present in the request')

        clearblade_config = self._cb_config.regional_config(request.name)
        
        body = self._create_registry_body(request.device_registry)
        params = {'name':request.name, 'updateMask': request.update_mask}
        sync_client = SyncClient(clearblade_config=clearblade_config)
        response = sync_client.patch(api_name = "cloudiot",request_body=body,request_params=params)
        return DeviceRegistry.from_json(response.json())

    async def patch_async(self,
        request: UpdateDeviceRegistryRequest = None)->DeviceRegistry:
        
        if request.name == None:
            raise Exception('Registry Path is not present in the request')

        body = self._create_registry_body(request.device_registry)
        params = {'name':request.name, 'updateMask': request.update_mask}
        clearblade_config=await self._cb_config.regional_config_async(request.name)
        async_client = AsyncClient(clearblade_config=clearblade_config)
        response = await async_client.patch(api_name = "cloudiot",request_body=body,request_params=params)
        return DeviceRegistry.from_json(response.json())