# Copyright 2016 Canonical Ltd.
#
# 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
#
#     http://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.

import asyncio
import logging

from . import model
from .client import client
from .errors import JujuError
from .placement import parse as parse_placement

log = logging.getLogger(__name__)


class Application(model.ModelEntity):
    @property
    def _unit_match_pattern(self):
        return r'^{}.*$'.format(self.entity_id)

    def on_unit_add(self, callable_):
        """Add a "unit added" observer to this entity, which will be called
        whenever a unit is added to this application.

        """
        self.model.add_observer(
            callable_, 'unit', 'add', self._unit_match_pattern)

    def on_unit_remove(self, callable_):
        """Add a "unit removed" observer to this entity, which will be called
        whenever a unit is removed from this application.

        """
        self.model.add_observer(
            callable_, 'unit', 'remove', self._unit_match_pattern)

    @property
    def units(self):
        return [
            unit for unit in self.model.units.values()
            if unit.application == self.name
        ]

    @property
    def relations(self):
        return [rel for rel in self.model.relations if rel.matches(self.name)]

    def related_applications(self, endpoint_name=None):
        apps = {}
        for rel in self.relations:
            if rel.is_peer:
                local_ep, remote_ep = rel.endpoints[0]
            else:
                def is_us(ep):
                    return ep.application.name == self.name
                local_ep, remote_ep = sorted(rel.endpoints, key=is_us)
            if endpoint_name is not None and endpoint_name != local_ep.name:
                continue
            apps[remote_ep.application.name] = remote_ep.application
        return apps

    @property
    def status(self):
        """Get the application status, as set by the charm's leader.

        """
        return self.safe_data['status']['current']

    @property
    def status_message(self):
        """Get the application status message, as set by the charm's leader.

        """
        return self.safe_data['status']['message']

    @property
    def tag(self):
        return 'application-%s' % self.name

    async def add_relation(self, local_relation, remote_relation):
        """Add a relation to another application.

        :param str local_relation: Name of relation on this application
        :param str remote_relation: Name of relation on the other
            application in the form '<application>[:<relation_name>]'

        """
        if ':' not in local_relation:
            local_relation = '{}:{}'.format(self.name, local_relation)

        return await self.model.add_relation(local_relation, remote_relation)

    async def add_unit(self, count=1, to=None):
        """Add one or more units to this application.

        :param int count: Number of units to add
        :param str to: Placement directive, e.g.::
            '23' - machine 23
            'lxc:7' - new lxc container on machine 7
            '24/lxc/3' - lxc container 3 or machine 24

            If None, a new machine is provisioned.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Adding %s unit%s to %s',
            count, '' if count == 1 else 's', self.name)

        result = await app_facade.AddUnits(
            application=self.name,
            placement=parse_placement(to) if to else None,
            num_units=count,
        )

        return await asyncio.gather(*[
            asyncio.ensure_future(self.model._wait_for_new('unit', unit_id))
            for unit_id in result.units
        ])

    add_units = add_unit

    def allocate(self, budget, value):
        """Allocate budget to this application.

        :param str budget: Name of budget
        :param int value: Budget limit

        """
        raise NotImplementedError()

    def attach(self, resource_name, file_path):
        """Upload a file as a resource for this application.

        :param str resource: Name of the resource
        :param str file_path: Path to the file to upload

        """
        raise NotImplementedError()

    def collect_metrics(self):
        """Collect metrics on this application.

        """
        raise NotImplementedError()

    async def destroy_relation(self, local_relation, remote_relation):
        """Remove a relation to another application.

        :param str local_relation: Name of relation on this application
        :param str remote_relation: Name of relation on the other
            application in the form '<application>[:<relation_name>]'

        """
        if ':' not in local_relation:
            local_relation = '{}:{}'.format(self.name, local_relation)

        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Destroying relation %s <-> %s', local_relation, remote_relation)

        return await app_facade.DestroyRelation([
            local_relation, remote_relation])
    remove_relation = destroy_relation

    async def destroy_unit(self, *unit_names):
        """Destroy units by name.

        """
        return await self.model.destroy_units(*unit_names)
    destroy_units = destroy_unit

    async def destroy(self):
        """Remove this application from the model.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Destroying %s', self.name)

        return await app_facade.Destroy(self.name)
    remove = destroy

    async def expose(self):
        """Make this application publicly available over the network.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Exposing %s', self.name)

        return await app_facade.Expose(self.name)

    async def get_config(self):
        """Return the configuration settings dict for this application.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Getting config for %s', self.name)

        return (await app_facade.Get(self.name)).config

    async def get_constraints(self):
        """Return the machine constraints dict for this application.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Getting constraints for %s', self.name)

        result = (await app_facade.Get(self.name)).constraints
        return vars(result) if result else result

    async def get_actions(self, schema=False):
        """Get actions defined for this application.

        :param bool schema: Return the full action schema
        :return dict: The charms actions, empty dict if none are defined.
        """
        actions = {}
        entity = [{"tag": self.tag}]
        action_facade = client.ActionFacade.from_connection(self.connection)
        results = (
            await action_facade.ApplicationsCharmsActions(entity)).results
        for result in results:
            if result.application_tag == self.tag and result.actions:
                actions = result.actions
                break
        if not schema:
            actions = {k: v['description'] for k, v in actions.items()}
        return actions

    def get_resources(self, details=False):
        """Return resources for this application.

        :param bool details: Include detailed info about resources used by each
            unit

        """
        raise NotImplementedError()

    async def run(self, command, timeout=None):
        """Run command on all units for this application.

        :param str command: The command to run
        :param int timeout: Time to wait before command is considered failed

        """
        action = client.ActionFacade.from_connection(self.connection)

        log.debug(
            'Running `%s` on all units of %s', command, self.name)

        # TODO this should return a list of Actions
        return await action.Run(
            [self.name],
            command,
            [],
            timeout,
            [],
        )

    async def set_annotations(self, annotations):
        """Set annotations on this application.

        :param annotations map[string]string: the annotations as key/value
            pairs.

        """
        log.debug('Updating annotations on application %s', self.name)

        self.ann_facade = client.AnnotationsFacade.from_connection(
            self.connection)

        ann = client.EntityAnnotations(
            entity=self.tag,
            annotations=annotations,
        )
        return await self.ann_facade.Set([ann])

    async def set_config(self, config):
        """Set configuration options for this application.

        :param config: Dict of configuration to set
        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Setting config for %s: %s', self.name, config)

        return await app_facade.Set(self.name, config)

    async def reset_config(self, to_default):
        """
        Restore application config to default values.

        :param list to_default: A list of config options to be reset to their default value.
        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Restoring default config for %s: %s', self.name, to_default)

        return await app_facade.Unset(self.name, to_default)

    async def set_constraints(self, constraints):
        """Set machine constraints for this application.

        :param dict constraints: Dict of machine constraints

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Setting constraints for %s: %s', self.name, constraints)

        return await app_facade.SetConstraints(self.name, constraints)

    def set_meter_status(self, status, info=None):
        """Set the meter status on this status.

        :param str status: Meter status, e.g. 'RED', 'AMBER'
        :param str info: Extra info message

        """
        raise NotImplementedError()

    def set_plan(self, plan_name):
        """Set the plan for this application, effective immediately.

        :param str plan_name: Name of plan

        """
        raise NotImplementedError()

    async def unexpose(self):
        """Remove public availability over the network for this application.

        """
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        log.debug(
            'Unexposing %s', self.name)

        return await app_facade.Unexpose(self.name)

    def update_allocation(self, allocation):
        """Update existing allocation for this application.

        :param int allocation: The allocation to set

        """
        raise NotImplementedError()

    async def upgrade_charm(
            self, channel=None, force_series=False, force_units=False,
            path=None, resources=None, revision=None, switch=None):
        """Upgrade the charm for this application.

        :param str channel: Channel to use when getting the charm from the
            charm store, e.g. 'development'
        :param bool force_series: Upgrade even if series of deployed
            application is not supported by the new charm
        :param bool force_units: Upgrade all units immediately, even if in
            error state
        :param str path: Uprade to a charm located at path
        :param dict resources: Dictionary of resource name/filepath pairs
        :param int revision: Explicit upgrade revision
        :param str switch: Crossgrade charm url

        """
        # TODO: Support local upgrades
        if path is not None:
            raise NotImplementedError("path option is not implemented")
        if resources is not None:
            raise NotImplementedError("resources option is not implemented")

        if switch is not None and revision is not None:
            raise ValueError("switch and revision are mutually exclusive")

        client_facade = client.ClientFacade.from_connection(self.connection)
        resources_facade = client.ResourcesFacade.from_connection(
            self.connection)
        app_facade = client.ApplicationFacade.from_connection(self.connection)

        charmstore = self.model.charmstore
        charmstore_entity = None

        if switch is not None:
            charm_url = switch
            if not charm_url.startswith('cs:'):
                charm_url = 'cs:' + charm_url
        else:
            charm_url = self.data['charm-url']
            charm_url = charm_url.rpartition('-')[0]
            if revision is not None:
                charm_url = "%s-%d" % (charm_url, revision)
            else:
                charmstore_entity = await charmstore.entity(charm_url,
                                                            channel=channel)
                charm_url = charmstore_entity['Id']

        if charm_url == self.data['charm-url']:
            raise JujuError('already running charm "%s"' % charm_url)

        # Update charm
        await client_facade.AddCharm(
            url=charm_url,
            channel=channel
        )

        # Update resources
        if not charmstore_entity:
            charmstore_entity = await charmstore.entity(charm_url,
                                                        channel=channel)
        store_resources = charmstore_entity['Meta']['resources']

        request_data = [client.Entity(self.tag)]
        response = await resources_facade.ListResources(request_data)
        existing_resources = {
            resource.name: resource
            for resource in response.results[0].resources
        }

        resources_to_update = [
            resource for resource in store_resources
            if resource['Name'] not in existing_resources or
            existing_resources[resource['Name']].origin != 'upload'
        ]

        if resources_to_update:
            request_data = [
                client.CharmResource(
                    description=resource.get('Description'),
                    fingerprint=resource['Fingerprint'],
                    name=resource['Name'],
                    path=resource['Path'],
                    revision=resource['Revision'],
                    size=resource['Size'],
                    type_=resource['Type'],
                    origin='store',
                ) for resource in resources_to_update
            ]
            response = await resources_facade.AddPendingResources(
                self.tag,
                charm_url,
                request_data
            )
            pending_ids = response.pending_ids
            resource_ids = {
                resource['Name']: id
                for resource, id in zip(resources_to_update, pending_ids)
            }
        else:
            resource_ids = None

        # Update application
        await app_facade.SetCharm(
            application=self.entity_id,
            channel=channel,
            charm_url=charm_url,
            config_settings=None,
            config_settings_yaml=None,
            force_series=force_series,
            force_units=force_units,
            resource_ids=resource_ids,
            storage_constraints=None
        )

        await self.model.block_until(
            lambda: self.data['charm-url'] == charm_url
        )

    async def get_metrics(self):
        """Get metrics for this application's units.

        :return: Dictionary of unit_name:metrics

        """
        return await self.model.get_metrics(self.tag)
