import os
from math import ceil
from decimal import Decimal
from django.test.client import Client
from django.template.loader import render_to_string
from django.template import Context
from django.db.models import get_model
from django.conf import settings


class Build():
    def write_file(self, path, object, ext='html',filename='index'):
        """
        Given a path and object intended to be a webpage, write the page the
        disc
        """
        path = '%s%s' %(settings.FLATFILES_ROOT, path)
        if not os.path.isdir(path):
            os.makedirs(path)
        fpath = '%s%s.%s' %(path, filename, ext)
        file = open(fpath, 'w')
        file.write(object)
        file.close()
        if ext == 'js':
            import jsmin
            compressed = jsmin.jsmin(object)
            fpath = '%s%s.min.%s' %(path, filename, ext)
            file = open(fpath, 'w')
            file.write(compressed)
            file.close()

    def build_archive_pages(self, qs=None, base_path='', paginate_by=10):
        """
        Archive Page builder that actually crawls the urls 
        because we need to be able to pass a request object to the template
        
        """
        if qs == None:
            qs = self.get_model_querset()
        c = Client()
        pages = ceil(Decimal(qs.count())/Decimal(paginate_by))
        for page in range(int(pages)):
            path = '%s%s/' %(base_path, page+1)
            url = '/%s%s/' %(base_path, str(page+1))
            page_url = base_path+'%d/'
            response = c.post(url, {'page_url': page_url, 'page': int(page), 'builder':True })
            if page == 0:
                self.write_file(base_path,str(response.content))
            self.write_file(path,str(response.content))
 
class BuildWriting(Build):
    def build(self):
        self.build_detail_pages()
        self.build_writing_archives()
        self.build_country_archive_pages()
        self.build_region_archive_pages()
        self.build_homepage()
        self.writing_year_archives()
        self.writing_month_archives()

    def get_model_querset(self):
        model = get_model('blog', 'entry')
        qs = model.objects.filter(status__exact=1)
        return qs
        
    def build_detail_pages(self):
        '''
        Grab all the blog posts, render them to a template string and write that out to the filesystem
        '''
        qs = self.get_model_querset()
        for entry in qs:
            c = Context({'object':entry,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
            t = render_to_string('details/entry.html',c).encode('utf-8') 
            path = '%s/%s/' %(entry.pub_date.strftime("%Y/%b/%d").lower(), entry.slug)
            self.write_file(path,t)
            s = render_to_string('details/entry.txt',c).encode('utf-8') 
            self.write_file(path,s,'txt')


    def build_writing_archives(self):
        qs = self.get_model_querset()
        self.build_archive_pages(qs, 'writing/')
   
    def build_region_archive_pages(self):
        model = get_model('locations', 'Region') 
        blog = get_model('blog', 'entry')
        regions = model.objects.all()
        for c in regions:
            qs = blog.objects.filter(status__exact=1,location__state__country__region = c.id).order_by('-pub_date')
            path = 'writing/%s/' %(c.slug)
            self.build_archive_pages(qs, path)

    def build_country_archive_pages(self):
        model = get_model('locations', 'Country') 
        blog = get_model('blog', 'entry')
        countries = model.objects.filter(visited=True)
        for c in countries:
            qs = blog.objects.filter(status__exact=1,location__state__country = c).order_by('-pub_date')
            path = 'writing/%s/' %(c.slug)
            self.build_archive_pages(qs, path)
   
    def writing_year_archives(self):
        entry = get_model('blog', 'entry')
        years = entry.objects.dates('pub_date', 'year')
        for year in years:
            year = year.strftime('%Y')
            qs = entry.objects.filter(status__exact=1,pub_date__year=year).order_by('-pub_date')
            c = Context({'type':'year','date': year, 'object_list':qs,})
            t = render_to_string('archives/writing_date.html',c).encode('utf-8') 
            fpath = '%s/' %(year) 
            self.write_file(fpath,t)

    def writing_month_archives(self): 
        entry = get_model('blog', 'entry')
        months = entry.objects.dates('pub_date', 'month')
        for m in months:
            year = m.strftime('%Y')
            month = m.strftime('%m')
            month_name = m.strftime('%b')
            month_full_name = m.strftime('%B')
            qs = entry.objects.filter(status__exact=1,pub_date__year=year,pub_date__month=month).order_by('-pub_date')
            c = Context({'type':'monthly','date': '%s %s' %(month_full_name,year), 'object_list':qs,})
            t = render_to_string('archives/writing_date.html',c).encode('utf-8') 
            fpath = '%s/%s/' %(year,month_name) 
            self.write_file(fpath,t)
   
    def build_homepage(self):
        qs = get_model('blog', 'entry').objects.filter(status__exact=1)[:4]
        c = Context({'object_list':qs,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
        t = render_to_string('archives/homepage.html',c).encode('utf-8') 
        self.write_file('',t)

class BuildPhotos(Build):
    def build(self):
        self.build_photo_archive_pages()
        self.build_detail_pages()
        
    def build_photo_archive_pages(self):
        qs = get_model('photos', 'PhotoGallery').objects.all()
        self.build_archive_pages(qs, 'photos/', 18)
        
    def build_detail_pages(self):
        qs = get_model('photos', 'PhotoGallery').objects.all()
        for photo in qs:
            c = Context({'object':photo,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
            t = render_to_string('details/photo_galleries.html',c).encode('utf-8') 
            path = 'photos/galleries/%s/' %(photo.set_slug)
            self.write_file(path,t)

class BuildProjects(Build):
    def build(self):
        self.build_project_archive()
        self.build_project_details()
        self.build_project_data()
        self.build_gifs()

    def get_projects(self):
        all_proj = []
        projects = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date')
        for proj in projects:
            row = {'slug':proj.slug, 'name':proj.model_name}
            all_proj.append(row)
        return all_proj
    
    def build_project_archive(self):
        qs = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date')
        c = Context({'object_list': qs,'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL})
        t = render_to_string('archives/projects.html', c).encode('utf-8') 
        self.write_file('projects/',t)
    
    def build_project_details(self):
        projects = self.get_projects()
        for proj in projects:
            model = get_model('projects', proj['name'])
            if proj['name'] == 'NationalParks':
                qs = model.objects.filter(visited__exact=True).order_by("-date_visited_begin")
            else:
                qs = model.objects.filter(status__exact=1)
            c = Context({'object_list': qs,'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL})
            t = render_to_string('details/%s.html' %(proj['slug']), c).encode('utf-8') 
            path = 'projects/%s/' %(proj['slug'])
            self.write_file(path,t)
    
    """
    not sure how to handle projects really, the above doesn't work and
    if I just keep writing if/else statements that gets messy, so I guess
    functions it is.
    """
    def build_gifs(self):
        qs = get_model('projects', 'AnimatedGif').objects.all()
        for gif in qs:
            c = Context({'object':gif,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
            t = render_to_string('details/gifs.html',c).encode('utf-8') 
            path = 'projects/gifs/%s/' %(gif.slug)
            self.write_file(path,t)




    def build_project_data(self):
        from projects.shortcuts import render_to_geojson
        model = get_model('projects', 'NationalParks')
        for park in model.objects.filter(visited__exact=True):
            qs = model.objects.filter(pk=park.id)
            json = render_to_geojson(
                qs,
                included_fields=['id',],
                geom_attribute='mpoly',
                mimetype = 'application/json',
            ) 
            json = str(json)
            json ="\n".join(json.splitlines()[3:])
            #print json
            path = 'projects/data/natparks/'
            self.write_file(path, json, 'json', park.id)

class BuildSitemap(Build):
    def build(self):
        c = Client()
        response = c.get('/sitemap.xml')
        self.write_file('',str(response.content), 'xml','sitemap')

class BuildWritingFeed(Build):
    def build(self):
        qs = get_model('blog', 'entry').objects.filter(status__exact=1).order_by('-pub_date')[:20]
        c = Context({'object_list':qs,'SITE_URL':settings.SITE_URL})
        t = render_to_string('feed.xml',c).encode('utf-8') 
        fpath = '%s' %('rss/',) 
        self.write_file(fpath,t,'xml')

class BuildMap(Build):
    def build(self):
        qs = get_model('blog', 'entry').objects.filter(status__exact=1)
        cl = get_model('locations', 'Country').objects.filter(visited=True).exclude(name='default')
        rl = get_model('locations', 'Region').objects.all()
        rtl = get_model('locations', 'Route').objects.all()
        c = Context({'object_list':qs, 'country_list':cl,'region_list':rl, 'route_list':rtl, 'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
        t = render_to_string('archives/map_data.html',c).encode('utf-8') 
        self.write_file('media/js/',t, 'js','mainmap')
        c = Context({'country_list':cl,'region_list':rl,'route_list':rtl,'MEDIA_URL':settings.BAKED_MEDIA_URL, 'IMAGES_URL':settings.BAKED_IMAGES_URL})
        t = render_to_string('archives/map.html',c).encode('utf-8') 
        self.write_file('map/',t)
        
class BuildPages(Build):
    def build(self):
        model = get_model('pages', 'page')
        pages = model.objects.all()
        for page in pages:
            c = Context({'object':page,'SITE_URL':settings.SITE_URL, 'MEDIA_URL':settings.BAKED_MEDIA_URL,'IMAGES_URL':settings.BAKED_IMAGES_URL})
            t = render_to_string(["details/%s.html" % page.slug, 'details/page.html'],c).encode('utf-8') 
            s = render_to_string('details/page.txt',c).encode('utf-8') 
            fpath = '%s/' %(page.slug)
            self.write_file(fpath,t)
            self.write_file(fpath,s,'txt')



class BuildContact(Build):
    def build(self):
        c = Client()
        response = c.get('/contact/')
        path = '%scontact/' %(settings.BAKED_ROOT)
        if not os.path.isdir(path):
            os.makedirs(path)
        fpath = '%sindex.html' %(path)
        self.write_file(fpath,str(response.content))
        
#class BuildCodeSite(Build):