import logging

from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from django import forms
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse

from .cms_models import (
    DCLBannerItemPluginModel, DCLBannerListPluginModel, DCLContactPluginModel,
    DCLFooterPluginModel, DCLLinkPluginModel, DCLNavbarDropdownPluginModel,
    DCLSectionIconPluginModel, DCLSectionImagePluginModel,
    DCLSectionPluginModel, DCLNavbarPluginModel,
    DCLSectionPromoPluginModel, DCLCalculatorPluginModel
)
from .models import VMTemplate, VMPricing
from datacenterlight.utils import clear_all_session_vars
from opennebula_api.serializers import VMTemplateSerializer

logger = logging.getLogger(__name__)


@plugin_pool.register_plugin
class DCLSectionPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Section Plugin"
    model = DCLSectionPluginModel
    render_template = "datacenterlight/cms/section.html"
    cache = False
    allow_children = True
    child_classes = [
        'DCLSectionIconPlugin', 'DCLSectionImagePlugin',
        'DCLSectionPromoPlugin', 'UngleichHTMLPlugin', 'DCLCalculatorPlugin'
    ]

    def render(self, context, instance, placeholder):
        context = super(DCLSectionPlugin, self).render(
            context, instance, placeholder
        )
        context['children_to_side'] = []
        context['children_to_content'] = []
        context['children_calculator'] = []
        if instance.child_plugin_instances is not None:
            right_children = [
                'DCLSectionImagePluginModel',
                'DCLSectionIconPluginModel',
            ]
            for child in instance.child_plugin_instances:
                if child.__class__.__name__ in right_children:
                    context['children_to_side'].append(child)
                elif child.plugin_type == 'DCLCalculatorPlugin':
                    context['children_calculator'].append(child)
                else:
                    context['children_to_content'].append(child)
        return context


@plugin_pool.register_plugin
class DCLSectionIconPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Section Icon Plugin"
    model = DCLSectionIconPluginModel
    render_template = "datacenterlight/cms/section_icon.html"
    cache = False
    require_parent = True


@plugin_pool.register_plugin
class DCLSectionImagePlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Section Image Plugin"
    model = DCLSectionImagePluginModel
    render_template = "datacenterlight/cms/section_image.html"
    cache = False
    require_parent = True


@plugin_pool.register_plugin
class DCLSectionPromoPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Section Promo Plugin"
    model = DCLSectionPromoPluginModel
    render_template = "datacenterlight/cms/section_promo.html"
    cache = False


@plugin_pool.register_plugin
class DCLCalculatorPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Calculator Plugin"
    model = DCLCalculatorPluginModel
    render_template = "datacenterlight/cms/calculator.html"
    cache = False
    require_parent = True

    def render(self, context, instance, placeholder):
        clear_all_session_vars(context['request'])

        if instance and hasattr(instance, 'template'):
            self.render_template = instance.template
        request = context['request']
        if request.method == "POST" and "order_form" in request.POST.keys():
            cores = request.POST.get('cpu')
            cores_field = forms.IntegerField(validators=[self.validate_cores])
            memory = request.POST.get('ram')
            memory_field = forms.FloatField(validators=[self.validate_memory])
            storage = request.POST.get('storage')
            storage_field = forms.IntegerField(
                validators=[self.validate_storage])
            template_id = int(request.POST.get('config'))
            pricing_name = request.POST.get('pricing_name')
            vm_pricing = VMPricing.get_vm_pricing_by_name(pricing_name)
            template = VMTemplate.objects.filter(
                opennebula_vm_template_id=template_id).first()
            template_data = VMTemplateSerializer(template).data

            if vm_pricing is None:
                vm_pricing_name_msg = _(
                    "Incorrect pricing name. Please contact support"
                    "{support_email}".format(
                        support_email=settings.DCL_SUPPORT_FROM_ADDRESS
                    )
                )
                messages.add_message(
                    request, messages.ERROR, vm_pricing_name_msg,
                    extra_tags='pricing'
                )
                return redirect(self)
            else:
                vm_pricing_name = vm_pricing.name

            try:
                cores = cores_field.clean(cores)
            except ValidationError as err:
                msg = '{} : {}.'.format(cores, str(err))
                messages.add_message(request, messages.ERROR, msg,
                                     extra_tags='cores')
                return redirect(self)

            try:
                memory = memory_field.clean(memory)
            except ValidationError as err:
                msg = '{} : {}.'.format(memory, str(err))
                messages.add_message(request, messages.ERROR, msg,
                                     extra_tags='memory')
                return redirect(self)

            try:
                storage = storage_field.clean(storage)
            except ValidationError as err:
                msg = '{} : {}.'.format(storage, str(err))
                messages.add_message(request, messages.ERROR, msg,
                                     extra_tags='storage')
                return redirect(self)

            price, vat, vat_percent, discount = get_vm_price_with_vat(
                cpu=cores,
                memory=memory,
                ssd_size=storage,
                pricing_name=vm_pricing_name
            )

            specs = {
                'cpu': cores,
                'memory': memory,
                'disk_size': storage,
                'discount': discount,
                'price': price,
                'vat': vat,
                'vat_percent': vat_percent,
                'total_price': round(price + vat - discount['amount'], 2),
                'pricing_name': vm_pricing_name
            }

            request.session['specs'] = specs
            request.session['template'] = template_data
            return redirect(reverse('datacenterlight:payment'))
        else:
            context = super(DCLCalculatorPlugin, self).render(
                context, instance, placeholder
            )
            ids = instance.vm_templates_to_show
            if ids:
                context['templates'] = VMTemplate.objects.filter(
                    vm_type=instance.vm_type
                ).filter(opennebula_vm_template_id__in=ids).order_by('name')
            else:
                context['templates'] = VMTemplate.objects.filter(
                    vm_type=instance.vm_type
                ).order_by('name')
            context['instance'] = instance
            context['min_ram'] = 0.5 if instance.enable_512mb_ram else 1
            return context

    def validate_cores(self, value):
        if (value > 48) or (value < 1):
            raise ValidationError(_('Invalid number of cores'))

    def validate_memory(self, value):
        if 'pid' in request.POST:
            try:
                plugin = DCLCalculatorPluginModel.objects.get(
                             id=request.POST['pid']
                         )
            except DCLCalculatorPluginModel.DoesNotExist as dne:
                logger.error(
                    str(dne) + " plugin_id: " + request.POST['pid']
                )
                raise ValidationError(_('Invalid calculator properties'))
            if plugin.enable_512mb_ram:
                if value % 1 == 0 or value == 0.5:
                    logger.debug(
                        "Given ram {value} is either 0.5 or a"
                        " whole number".format(value=value)
                    )
                    if (value > 200) or (value < 0.5):
                        raise ValidationError(_('Invalid RAM size'))
                else:
                    raise ValidationError(_('Invalid RAM size'))
            elif (value > 200) or (value < 1) or (value % 1 != 0):
                raise ValidationError(_('Invalid RAM size'))
        else:
            raise ValidationError(_('Invalid RAM size'))

    def validate_storage(self, value):
        if (value > 2000) or (value < 10):
            raise ValidationError(_('Invalid storage size'))

@plugin_pool.register_plugin
class DCLBannerListPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Banner List Plugin"
    model = DCLBannerListPluginModel
    render_template = "datacenterlight/cms/banner_list.html"
    cache = False
    allow_children = True
    child_classes = ['DCLBannerItemPlugin']


@plugin_pool.register_plugin
class DCLBannerItemPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Banner Item Plugin"
    model = DCLBannerItemPluginModel
    render_template = "datacenterlight/cms/banner_item.html"
    cache = False
    require_parent = True
    parent_classes = ['DCLBannerListPlugin']


@plugin_pool.register_plugin
class DCLNavbarPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Navbar Plugin"
    model = DCLNavbarPluginModel
    render_template = "datacenterlight/cms/navbar.html"
    cache = False
    allow_children = True
    child_classes = ['DCLLinkPlugin', 'DCLNavbarDropdownPlugin']


@plugin_pool.register_plugin
class DCLNavbarDropdownPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Navbar Dropdown Plugin"
    model = DCLNavbarDropdownPluginModel
    render_template = "datacenterlight/cms/navbar_dropdown.html"
    cache = False
    allow_children = True
    child_classes = ['DCLLinkPlugin']
    require_parent = True
    parent_classes = ['DCLNavbarPlugin']


@plugin_pool.register_plugin
class DCLLinkPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Link Plugin"
    model = DCLLinkPluginModel
    render_template = "datacenterlight/cms/link.html"
    cache = False
    require_parent = True


@plugin_pool.register_plugin
class DCLContactPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Contact Plugin"
    model = DCLContactPluginModel
    render_template = "datacenterlight/cms/contact.html"
    cache = False


@plugin_pool.register_plugin
class DCLFooterPlugin(CMSPluginBase):
    module = "Datacenterlight"
    name = "DCL Footer Plugin"
    model = DCLFooterPluginModel
    render_template = "datacenterlight/cms/footer.html"
    cache = False
    allow_children = True
    child_classes = ['DCLLinkPlugin']