# Copyright (c) 2014 eBay Software Foundation
# Copyright 2015 HP Software, LLC
# 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. 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.

from django.core import urlresolvers
from django.template.defaultfilters import title  # noqa
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy

from horizon import tables
from horizon.templatetags import sizeformat
from horizon.utils import filters
from horizon.utils import memoized

from trove_dashboard import api
from trove_dashboard.content.databases import db_capability

ACTIVE_STATES = ("ACTIVE",)


class DeleteCluster(tables.BatchAction):
    name = "delete"
    icon = "remove"
    classes = ('btn-danger',)
    help_text = _("Deleted cluster is not recoverable.")

    @staticmethod
    def action_present(count):
        return ungettext_lazy(
            u"Delete Cluster",
            u"Delete Clusters",
            count
        )

    @staticmethod
    def action_past(count):
        return ungettext_lazy(
            u"Scheduled deletion of Cluster",
            u"Scheduled deletion of Clusters",
            count
        )

    def action(self, request, obj_id):
        api.trove.cluster_delete(request, obj_id)


class LaunchLink(tables.LinkAction):
    name = "launch"
    verbose_name = _("Launch Cluster")
    url = "horizon:project:database_clusters:launch"
    classes = ("btn-launch", "ajax-modal")
    icon = "cloud-upload"


class AddShard(tables.LinkAction):
    name = "add_shard"
    verbose_name = _("Add Shard")
    url = "horizon:project:database_clusters:add_shard"
    classes = ("ajax-modal",)
    icon = "plus"

    def allowed(self, request, cluster=None):
        if (cluster and cluster.task["name"] == 'NONE' and
                db_capability.is_mongodb_datastore(cluster.datastore['type'])):
            return True
        return False


class ResetPassword(tables.LinkAction):
    name = "reset_password"
    verbose_name = _("Reset Root Password")
    url = "horizon:project:database_clusters:reset_password"
    classes = ("ajax-modal",)

    def allowed(self, request, cluster=None):
        if (cluster and cluster.task["name"] == 'NONE' and
                db_capability.is_vertica_datastore(cluster.datastore['type'])):
            return True
        return False

    def get_link_url(self, datum):
        cluster_id = self.table.get_object_id(datum)
        return urlresolvers.reverse(self.url, args=[cluster_id])


class UpdateRow(tables.Row):
    ajax = True

    @memoized.memoized_method
    def get_data(self, request, cluster_id):
        cluster = api.trove.cluster_get(request, cluster_id)
        try:
            # TODO(michayu): assumption that cluster is homogeneous
            flavor_id = cluster.instances[0]['flavor']['id']
            cluster.full_flavor = api.trove.flavor_get(request, flavor_id)
        except Exception:
            pass
        return cluster


def get_datastore(cluster):
    return cluster.datastore["type"]


def get_datastore_version(cluster):
    return cluster.datastore["version"]


def get_size(cluster):
    if db_capability.is_vertica_datastore(cluster.datastore['type']):
        return "3"

    if hasattr(cluster, "full_flavor"):
        size_string = _("%(name)s | %(RAM)s RAM | %(instances)s instances")
        vals = {'name': cluster.full_flavor.name,
                'RAM': sizeformat.mbformat(cluster.full_flavor.ram),
                'instances': len(cluster.instances)}
        return size_string % vals
    return _("Not available")


def get_task(cluster):
    return cluster.task["name"]


class ClustersTable(tables.DataTable):
    TASK_CHOICES = (
        ("none", True),
    )
    name = tables.Column("name",
                         link=("horizon:project:database_clusters:detail"),
                         verbose_name=_("Cluster Name"))
    datastore = tables.Column(get_datastore,
                              verbose_name=_("Datastore"))
    datastore_version = tables.Column(get_datastore_version,
                                      verbose_name=_("Datastore Version"))
    size = tables.Column(get_size,
                         verbose_name=_("Cluster Size"),
                         attrs={'data-type': 'size'})
    task = tables.Column(get_task,
                         filters=(title, filters.replace_underscores),
                         verbose_name=_("Current Task"),
                         status=True,
                         status_choices=TASK_CHOICES)

    class Meta(object):
        name = "clusters"
        verbose_name = _("Clusters")
        status_columns = ["task"]
        row_class = UpdateRow
        table_actions = (LaunchLink, DeleteCluster)
        row_actions = (AddShard, ResetPassword, DeleteCluster)


def get_instance_size(instance):
    if hasattr(instance, "full_flavor"):
        size_string = _("%(name)s | %(RAM)s RAM")
        vals = {'name': instance.full_flavor.name,
                'RAM': sizeformat.mbformat(instance.full_flavor.ram)}
        return size_string % vals
    return _("Not available")


def get_instance_type(instance):
    if hasattr(instance, "type"):
        return instance.type
    return _("Not available")


def get_host(instance):
    if hasattr(instance, "hostname"):
        return instance.hostname
    elif hasattr(instance, "ip") and instance.ip:
        return instance.ip[0]
    return _("Not Assigned")


class InstancesTable(tables.DataTable):
    name = tables.Column("name",
                         verbose_name=_("Name"))
    type = tables.Column(get_instance_type,
                         verbose_name=_("Type"))
    host = tables.Column(get_host,
                         verbose_name=_("Host"))
    size = tables.Column(get_instance_size,
                         verbose_name=_("Size"),
                         attrs={'data-type': 'size'})
    status = tables.Column("status",
                           filters=(title, filters.replace_underscores),
                           verbose_name=_("Status"))

    class Meta(object):
        name = "instances"
        verbose_name = _("Instances")
