# -*- coding: utf8 -*-
#
#    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 json

from django.core.urlresolvers import reverse
from django import http
from django.utils.translation import ugettext_lazy as _
from django.views.generic import base
from glanceclient import exc as glance_exc
from horizon import tables as horizon_tables
from horizon import utils
from horizon import workflows
from openstack_dashboard.api import base as api_base

from tuskar_ui import api
from tuskar_ui.infrastructure.roles import tables
from tuskar_ui.infrastructure.roles import workflows as role_workflows
from tuskar_ui.infrastructure import views
from tuskar_ui.utils import metering as metering_utils


INDEX_URL = 'horizon:infrastructure:roles:index'


class IndexView(views.ItemCountMixin, horizon_tables.DataTableView):
    table_class = tables.RolesTable
    template_name = "infrastructure/roles/index.html"

    @utils.memoized.memoized
    def get_data(self):
        roles = api.tuskar.Role.list(self.request)
        plan = api.tuskar.Plan.get_the_plan(self.request)
        for role in roles:
            role_flavor = role.flavor(plan)
            try:
                role_image = role.image(plan)
            except glance_exc.HTTPNotFound:
                # Glance returns a 404 if the image doesn't exist
                role_image = None
            if role_flavor:
                role.flavor = role_flavor.name
            else:
                role.flavor = _('Unknown')
            if role_image:
                role.image = role_image.name
            else:
                role.image = _('Unknown')

        return roles


class DetailView(horizon_tables.DataTableView, views.RoleMixin,
                 views.StackMixin):
    table_class = tables.NodeTable
    template_name = 'infrastructure/roles/detail.html'

    @utils.memoized.memoized
    def _get_nodes(self, stack, role):
        resources = stack.resources(role=role, with_joins=True)
        nodes = [r.node for r in resources]
        for node in nodes:
            try:
                resource = api.heat.Resource.get_by_node(self.request, node)
            except LookupError:
                node.role_name = '-'
            else:
                node.role_name = resource.role.name
                node.role_id = resource.role.id
                node.stack_id = resource.stack.id

        return nodes

    def get_data(self):
        redirect = reverse(INDEX_URL)
        stack = self.get_stack()
        if stack:
            role = self.get_role(redirect)
            return self._get_nodes(stack, role)
        return []

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)
        redirect = reverse(INDEX_URL)

        plan = api.tuskar.Plan.get_the_plan(self.request)
        stack = self.get_stack()
        role = self.get_role(redirect)

        context['role'] = role
        if stack:
            context['nodes'] = self._get_nodes(stack, role)
        else:
            context['nodes'] = []
        context['flavor'] = role.flavor(plan)
        context['image'] = role.image(plan)

        if stack:
            if api_base.is_service_enabled(self.request, 'metering'):
                # Meter configuration in the following format:
                # (meter label, url part, barchart (True/False))
                context['meter_conf'] = (
                    (_('System Load'),
                     metering_utils.url_part('hardware.cpu.load.1min', False),
                     None),
                    (_('CPU Utilization'),
                     metering_utils.url_part('hardware.system_stats.cpu.util',
                                             True),
                     '100'),
                    (_('Swap Utilization'),
                     metering_utils.url_part('hardware.memory.swap.util',
                                             True),
                     '100'),
                )
        return context


class UpdateView(workflows.WorkflowView, views.StackMixin, views.RoleMixin):
    workflow_class = role_workflows.UpdateRole

    def get_initial(self):
        plan = self.get_plan()
        role = self.get_role()

        stack = self.get_stack()
        if stack:
            resources = stack.resources(role=role, with_joins=True)
            role_nodes = len(resources)
        else:
            role_nodes = 0

        role_flavor = role.flavor(plan)
        role_flavor = '' if role_flavor is None else role_flavor.name

        role_image = role.image(plan)
        role_image = '' if role_image is None else role_image.name

        free_nodes = len(api.node.Node.list(self.request, associated=False,
                                            maintenance=False))
        available_nodes = role_nodes + free_nodes

        return {
            'role_id': role.id,
            'name': role.name,
            'flavor': role_flavor,
            'image': role_image,
            'nodes': role_nodes,
            'available_nodes': available_nodes,
        }


class PerformanceView(base.TemplateView, views.RoleMixin, views.StackMixin):
    def get(self, request, *args, **kwargs):
        meter = request.GET.get('meter')
        date_options = request.GET.get('date_options')
        date_from = request.GET.get('date_from')
        date_to = request.GET.get('date_to')
        stats_attr = request.GET.get('stats_attr', 'avg')
        barchart = bool(request.GET.get('barchart'))

        role = self.get_role()
        stack = self.get_stack()
        instances = stack.resources(role=role, with_joins=True)

        if instances:
            instance_uuids = [i.physical_resource_id for i in instances]
            json_output = metering_utils.get_nodes_stats(
                request=request,
                node_uuid=None,
                instance_uuids=instance_uuids,
                meter=meter,
                date_options=date_options,
                date_from=date_from,
                date_to=date_to,
                stats_attr=stats_attr,
                barchart=barchart)
        else:
            json_output = None

        return http.HttpResponse(json.dumps(json_output),
                                 content_type='application/json')
