import csv
import pywapi
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta
from dateutil.parser import parse

from django import http
from django.template.loader import get_template
from django.template import Context
import ho.pisa as pisa
import cStringIO as StringIO
import cgi

from django.http import HttpResponse
from django.template.context import RequestContext
from django.views.generic import list_detail
from django.shortcuts import render_to_response

from almanac.models import (
    Tide,
    TideDay,
    TideChart,
    Day,
    WeatherConditions,
    WeatherAlert,
    WeatherForecast,
)
from darkroom.models import Webcam
from directory.models import Place, Point, Town


def index(request):
    webcams = Webcam.objects.all()
    towns = Town.objects.filter(in_coverage=True)
    town_weather = []
    for t in towns:
        if t.slug == "castine" or t.slug == "stonington" or t.slug == "blue-hill":
            town_weather.append(pywapi.get_weather_from_yahoo(t.zipcode, "imperial"))

    if datetime.now().hour > 20 or datetime.now().hour < 4:
        moon = "moon"
    else:
        moon = ""

    return render_to_response(
        "almanac/index.html", locals(), context_instance=RequestContext(request)
    )


def tide_index(request):
    charts = TideChart.objects.filter(public=True).order_by("-year")
    months = [
        "jan",
        "feb",
        "mar",
        "apr",
        "may",
        "jun",
        "jul",
        "sep",
        "oct",
        "nov",
        "dec",
    ]
    return render_to_response(
        "almanac/tide_index.html", locals(), context_instance=RequestContext(request)
    )


def tide_week_detail(request, slug, year, month, day):
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    start_date = parse(str(year) + "-" + month + "-" + str(day))
    end_date = start_date + timedelta(days=3)
    first_day_set = (
        TideDay.objects.filter(tide_chart__place__slug__exact=slug)
        .exclude(day__date__gt=end_date)
        .filter(day__date__gte=start_date)
    )

    second_start_date = start_date + timedelta(days=4)
    second_end_date = second_start_date + timedelta(days=3)
    second_day_set = (
        TideDay.objects.filter(tide_chart__place__slug__exact=slug)
        .exclude(day__date__gt=second_end_date)
        .filter(day__date__gte=second_start_date)
    )
    return render_to_response(
        "almanac/tide_week_detail.html",
        locals(),
        context_instance=RequestContext(request),
    )


def tide_month_detail(request, slug, year, month):
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    days = TideDay.objects.filter(
        tide_chart__place__slug__exact=slug,
        day__date__year=year,
        day__date__month=parse(month).month,
    )
    full_date = datetime(int(year), parse(month).month, 1)
    month = month.capitalize()
    today = date.today()
    return render_to_response(
        "almanac/tide_month_detail.html",
        locals(),
        context_instance=RequestContext(request),
    )


def tide_year_detail(request, slug, year):
    astro_days = Day.objects.filter(chart__year__exact=year)
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    return render_to_response(
        "almanac/tide_year_detail.html",
        locals(),
        context_instance=RequestContext(request),
    )


def seasonal_guide(request, slug, year, month, day):
    today = datetime.today()
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    start_date = parse(str(year) + "-" + month + "-" + str(day))
    end_date = start_date + relativedelta(months=+1, days=-1)

    days = (
        TideDay.objects.filter(tide_chart__place__slug=slug)
        .exclude(day__date__gt=end_date)
        .filter(day__date__gte=start_date)
    )
    n = len(days) / 2
    first_day_set = days[0:n]
    second_day_set = days[n:]

    # end_date=start_date+timedelta(days=13)
    # first_day_set=TideDay.objects.filter(tide_chart__place__slug__exact=slug).exclude(
    #                       day__date__gt=end_date).filter(
    #                       day__date__gte=start_date)

    # second_start_date=start_date+timedelta(days=14)
    # second_end_date=second_start_date+timedelta(days=13)
    # second_day_set=TideDay.objects.filter(tide_chart__place__slug__exact=slug).exclude(
    #                       day__date__gt=second_end_date).filter(
    #                       day__date__gte=second_start_date)
    noon = datetime(today.year, today.month, today.day, 12, 0)
    return render_to_response(
        "almanac/tide_seasonal_guide.html",
        locals(),
        context_instance=RequestContext(request),
    )


def weekly_dump(request, slug, year, month, day):
    response = HttpResponse(mimetype="text/csv")
    response["Content-Disposition"] = "attachment; filename=tides.csv"
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    start_date = parse(str(year) + "-" + month + "-" + str(day))
    end_date = start_date + timedelta(days=7)
    days = (
        TideDay.objects.filter(tide_chart__place__slug=slug)
        .exclude(day__date__gt=end_date)
        .filter(day__date__gte=start_date)
    )

    writer = csv.writer(response)
    for tday in days.all():
        day = tday.day
        tide1 = tday.tide_1
        tide2 = tday.tide_2
        tide3 = tday.tide_3
        tide4 = tday.tide_4
        if tide4:
            writer.writerow(
                [
                    tday.day.date,
                    tide1,
                    tide1.state,
                    tide1.level,
                    tide2,
                    tide2.state,
                    tide2.level,
                    tide3,
                    tide3.state,
                    tide3.level,
                    tide4,
                    tide4.state,
                    tide4.level,
                    day.moonphase,
                    day.moonphase_time,
                    day.moonrise,
                    day.moonset,
                    day.sunrise,
                    day.sunset,
                ]
            )
        else:
            writer.writerow(
                [
                    tday.day.date,
                    tide1,
                    tide1.state,
                    tide1.level,
                    tide2,
                    tide2.state,
                    tide2.level,
                    tide3,
                    tide3.state,
                    tide3.level,
                    "",
                    "",
                    "",
                    day.moonphase,
                    day.moonphase_time,
                    day.moonrise,
                    day.moonset,
                    day.sunrise,
                    day.sunset,
                ]
            )
    return response


def write_pdf(template_src, context_dict):
    template = get_template(template_src)
    context = Context(context_dict)
    html = template.render(context)
    result = StringIO.StringIO()
    pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result)
    if not pdf.err:
        return http.HttpResponse(result.getvalue(), mimetype="application/pdf")
    return http.HttpResponse("Gremlin's ate your pdf! %s" % cgi.escape(html))


def seasonal_guide_pdf(request, slug, year, month, day):
    today = datetime.today()
    chart = TideChart.objects.get(place__slug=slug, year__exact=year)
    start_date = parse(str(year) + "-" + month + "-" + str(day))
    end_date = start_date + relativedelta(months=+1, days=-1)

    days = (
        TideDay.objects.filter(tide_chart__place__slug=slug)
        .exclude(day__date__gt=end_date)
        .filter(day__date__gte=start_date)
    )
    n = len(days) / 2
    first_day_set = days[0:n]
    second_day_set = days[n:]

    noon = datetime(today.year, today.month, today.day, 12, 0)

    return write_pdf(
        "almanac/pdf/seasonal_guide.html",
        {
            "pagesize": "letter",
            "today": today,
            "noon": noon,
            "chart": chart,
            "days": days,
            "first_day_set": first_day_set,
            "second_day_set": second_day_set,
        },
    )
