import os
import time
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
from django.conf import settings
from django.core.urlresolvers import reverse
from django import template

from almanac.models import Day, Tide, TideDay, WeatherConditions

register = template.Library()


def show_tide_day_as_box(tideday):
    return {"day": tideday}


def bold_afternoon_time(time, format_string):
    """
      bold_afternoon_time is a template tag which takes a time and a format string.
      if the time is after noon on the current day, it returns a bolded html format of the time.
      otherwise it returns just the formated string.      
    """
    today = datetime.today()
    noon = datetime(today.year, today.month, today.day, 12, 0)
    if time:
        dtime = datetime(today.year, today.month, today.day, time.hour, time.minute)
        if dtime < noon:
            html = dtime.strftime(format_string.encode("ascii"))
        else:
            html = "<b>" + dtime.strftime(format_string.encode("ascii")) + "</b>"
    else:
        html = ""
    return html


def get_next_tide(date, slug):
    date_str = date.strftime("%Y-%m-%d")
    tday = TideDay.objects.get(tide_chart__place__slug=slug, day__date=date_str)
    if date.time() < tday.tide_1.time:
        return tday.tide_1
    elif date.time() < tday.tide_2.time:
        return tday.tide_2
    elif date.time() < tday.tide_3.time:
        return tday.tide_3
    elif tday.tide_4 and date.time() < tday.tide_4.time:
        return tday.tide_4
    else:  # Tide 4 either does not exist, or we are past it, set the tide to tomorrow's first tide.
        date = date + timedelta(days=1)
        date_str = date.strftime("%Y-%m-%d")
        tday2 = TideDay.objects.get(tide_chart__place__slug=slug, day__date=date_str)
        return tday2.tide_1
    return nil


def do_current_tide_state(parser, token):
    bits = token.contents.split()
    if len(bits) != 4:
        raise template.TemplateSyntaxError, "current_tide_state takes exactly three arguments"
    if bits[2] != "as":
        raise template.TemplateSyntaxError, "second argument to the current_tide_state tag must be 'as'"
    return CurrentTideStateNode(bits[1], bits[3])


class CurrentTideStateNode(template.Node):
    def __init__(self, slug, varname):
        self.slug, self.varname = slug, varname

    def render(self, context):
        today = datetime.today()
        next_tide = get_next_tide(today, self.slug)
        tide = {
            "time": next_tide.time,
            "state": next_tide.get_state_display(),
            "level": next_tide.level,
        }
        if tide["state"] == "Low":
            tide["status"] = "Ebbing"
        else:
            tide["status"] = "Rising"
        context[self.varname] = tide
        return ""


def do_current_conditions(parser, token):
    """
      Example: {% current_conditions stonington as ston_weather  %}
    """
    bits = token.contents.split()
    if len(bits) != 4:
        raise template.TemplateSyntaxError, "current_conditions takes exactly three arguments"
    if bits[2] != "as":
        raise template.TemplateSyntaxError, "second argument to the current_conditions tag must be 'as'"
    return CurrentConditionsNode(bits[1], bits[3])


class CurrentConditionsNode(template.Node):
    def __init__(self, slug, varname):
        self.slug, self.varname = slug, varname

    def render(self, context):
        conds = WeatherConditions.objects.filter(town__slug=self.slug).latest()
        condition = {
            "town": self.slug.capitalize(),
            "cond": conds.conditions,
            "temp": conds.temperature,
        }
        if datetime.now().hour > 20 or datetime.now().hour < 4:
            condition["moon"] = "moon"
        else:
            condition["moon"] = ""

        context[self.varname] = condition
        return ""


def do_temp_history(parser, token):
    """ 
      Example: {% temp_history 5 days in stonington as ston_history %}
               {% temp_history 3 hours in stonington as ston_history %}
    """
    bits = token.contents.split()
    if len(bits) != 7:
        raise template.TemplateSyntaxError, "temp_history takes exactly three arguments"
    if bits[3] != "in" or bits[5] != "as":
        raise template.TemplateSyntaxError, "fourth and sixth arguments to the temp_history tag must be 'in' and 'as'"
    return TempHistoryNode(bits[1], bits[2], bits[4], bits[6])


class TempHistoryNode(template.Node):
    def __init__(self, period, scale, slug, varname):
        self.scale, self.period, self.slug, self.varname = scale, period, slug, varname

    def render(self, context):
        history = {"scale": self.scale, "period": self.period}

        if self.scale == "days" or self.scale == "day":
            days_ago = datetime.now() + timedelta(days=-int(self.period))
            history["days"] = Day.objects.filter(
                date__gte=days_ago, date__lt=datetime.now().date()
            )
        elif self.scale == "hours" or self.scale == "hour":
            pass
        elif self.scale == "months" or self.scale == "month":
            history["days"] = []
            for i in range(int(self.period)):
                i += 1
                day = datetime.now().date() + relativedelta(months=-i)
                history["days"].append(Day.objects.filter(date=day))
        else:
            history["days"] = None

        context[self.varname] = history
        return ""


def do_temp_data(parser, token):
    """ 
      Example: {% temp_data 5 days in stonington as ston_data %}
               {% temp_data 3 hours in stonington as ston_data %}
    """
    bits = token.contents.split()
    if len(bits) != 7:
        raise template.TemplateSyntaxError, "temp_data takes exactly three arguments"
    if bits[3] != "in" or bits[5] != "as":
        raise template.TemplateSyntaxError, "fourth and sixth arguments to the temp_data tag must be 'in' and 'as'"
    return TempDataNode(bits[1], bits[2], bits[4], bits[6])


class TempDataNode(template.Node):
    def __init__(self, period, scale, slug, varname):
        self.scale, self.period, self.slug, self.varname = scale, period, slug, varname

    def render(self, context):
        data = {"scale": self.scale, "period": self.period}
        data["days"] = []
        data["temps"] = []
        data["labels"] = []
        if self.scale == "days" or self.scale == "day":
            days_ago = datetime.now() + timedelta(days=-int(self.period))
            days = Day.objects.filter(
                date__gte=days_ago, date__lt=datetime.now().date()
            )
            i = 0
            for day in days:
                data["days"].append(day.date.day)
                try:
                    temp = int(day.daily_avg_temp)
                except:
                    temp = 0
                data["temps"].append(temp)
                # Labels: Type, Contents, Color, Data point, Size, Priority
                label = ["text", str(temp), "000000", 0, i, 15]
                data["labels"].append(label)
                i += 1
        elif self.scale == "hours" or self.scale == "hour":
            pass
        elif self.scale == "months" or self.scale == "month":
            data["days"] = []
            data["temps"] = []
            for i in range(int(self.period)):
                i += 1
                day = Day.objects.filter(
                    date=datetime.now().date() + relativedelta(months=-i)
                )
                data["days"].append(day.date)
                data["temps"].append(day.monthly_avg_temp)
        else:
            data["days"] = None

        context[self.varname] = data
        return ""


register.tag("temp_data", do_temp_data)
register.tag("temp_history", do_temp_history)
register.tag("current_conditions", do_current_conditions)
register.tag("current_tide_state", do_current_tide_state)
register.simple_tag(bold_afternoon_time)
register.inclusion_tag("tide_day_box.html")(show_tide_day_as_box)
