#!/usr/bin/env python
# coding=utf-8
#
#  Copyright (c) 2013-2015 First Flamingo Enterprise B.V.
#
#  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.
#
#  TAToolsHandler.py
#  firstflamingo/treinenaapje
#
#  Created by Berend Schotanus on 06-Feb-13.
#

from google.appengine.ext import db
from google.appengine.api import memcache
import webapp2
import math, logging

from datetime   import datetime, timedelta

from ffe                import markup
from ffe.ffe_time       import mark_cet, utc_from_cet, minutes_from_string, string_from_minutes
from TASeries           import TASeries
from TAMission          import TAMission, round_mission_offset
from TAStop             import TAStop, StopStatuses
from TAScheduledPoint   import Direction

MENU_LIST = (('Home', '/console'),
             ('Series', '/console/series?page=1'),
             ('Missies zonder serie', '/console/missions?kind=orphans&page=1'),
             ('Stations', '/console/stations?page=1'),
             ('Rapportage', '/console/report'))

FIRST_HALF  = 0
SECND_HALF  = 1
ORD_LABEL   = ['Eerste', 'Tweede']

# URL Handlers

class RepatternHandler(webapp2.RequestHandler):
    
    def get(self):
        series =TASeries.get(self.request.get('series'))
        self.results = [{}, {}]
        self.analyzeStops()
        
        self.doc = ToolsDocument('Patroontijden voor serie %s' % series.name)
        
        form = markup.form('/tools/repattern', 'post')
        form.add(markup.input('hidden', 'series', self.request.get('series')))
        form.add(markup.heading(2, 'Heenrichting'))
        form.add(self.patternTimeTable(series, Direction.up))
        form.add(markup.heading(2, 'Terugrichting'))
        form.add(self.patternTimeTable(series, Direction.down))
        form.add(markup.input('submit', value='pas aan'))
        
        self.doc.main.add(form)
        self.response.out.write(self.doc.write())

    def post(self):
        series =TASeries.get(self.request.get('series'))
        self.doc = ToolsDocument('Aangepaste tijden voor serie %s' % series.name)
        processedObjects   = []
        processedPoints    = {}
        
        table = self.doc.add_table('changestable', ['Station', 'A', 'V', 'A', 'V', ''])
        for index in range(len(series.points)):
            point = series.points[index]
            oldTimes = point.scheduled_times
            upArrival = self.request.get('arr_%d_%d' % (Direction.up, index))
            upDeparture = self.request.get('dep_%d_%d' % (Direction.up, index))
            downArrival = self.request.get('arr_%d_%d' % (Direction.down, index))
            downDeparture = self.request.get('dep_%d_%d' % (Direction.down, index))
            newTimes = (minutes_from_string(upArrival),
                        minutes_from_string(upDeparture),
                        minutes_from_string(downArrival),
                        minutes_from_string(downDeparture))
            
            row = table.add_row()
            row.add_to_cell(0, point.stationName)
            row.add_to_cell(1, upArrival)
            row.add_to_cell(2, upDeparture)
            row.add_to_cell(3, downArrival)
            row.add_to_cell(4, downDeparture)
            
            if oldTimes != newTimes:
                point.scheduled_times = newTimes
                processedPoints[point.id] = point
                processedObjects.append(point)
                row.add_to_cell(5, 'aangepast')

        series.cache_set()
        memcache.set_multi(processedPoints, namespace='TAScheduledPoint')
        db.put(processedObjects)
        self.response.out.write(self.doc.write())

    def patternTimeTable(self, series, direction):
        table = markup.HTMLTable('timetable_%d' % direction, ['Station', 'A', 'V', 'meting', '#', 'delta', 'A', 'V'])
        indexes = range(len(series.points))
        if direction == Direction.down: ind
exes.reverse()
        for index in indexes:
            point = series.points[index]
            station = point.station
       
     planArrival, planDeparture = point.times_in_direction(direction)
            row = table.add_row()
            row.add_to_cell(0, station.name)
            row.add_to_cell(1, string_from_minutes(planArrival))
            row.add_to_cell(2, string_from_minutes(planDeparture))
            stationDict = self.results[direction].get(station.id, None)
            if stationDict == None:
                departure, count = ('-', '-')
                delta = 0
            else:
                departure, count = mostCommonItem(stationDict['v'])
                delta = departure - planDeparture
                departure = string_from_minutes(departure)
            row.add_to_cell(3, departure)
            row.add_to_cell(4, count)
            row.add_to_cell(5, delta)
            row.add_to_cell(6, markup.input('text', 'arr_%d_%d' % (direction, index), string_from_minutes(planArrival + delta), size=4))
            row.add_to_cell(7, markup.input('text', 'dep_%d_%d' % (direction, index), string_from_minutes(planDeparture + delta), size=4))
        return table

    def analyzeStops(self):
        series_id = self.request.get('series')
        query = db.Query(TAArchivedMission).filter('series_id =', series_id)
        for mission in query.fetch(50):
            if mission.up: direction = Direction.up
            else: direction = Direction.down
            for stop in mission.stopsList:
                stopKey = stop.station_id
                if stop.status == StopStatuses.planned:
                    departureHist = self.histogram(direction, stopKey, 'v')
                    difference = utc_from_cet(stop.departure) - correctedOffsetUTC(mission)
                    self.addDataToHistogram(departureHist, difference.seconds // 60)
                    delayHist = self.histogram(direction, stopKey, 'dv')
                    self.addDataToHistogram(delayHist, int(stop.delay_dep))
                    platformHist = self.histogram(direction, stopKey, 'p')
                    self.addDataToHistogram(platformHist, stop.platform)

    def stopDictionary(self, direction, stopKey):
        dictionary = self.results[direction].get(stopKey, None)
        if dictionary == None:
            dictionary = dict()
            self.results[direction][stopKey] = dictionary
        return dictionary
    
    def histogram(self, direction, stopKey, dataKey):
        stopDictionary = self.stopDictionary(direction, stopKey)
        dictionary = stopDictionary.get(dataKey, None)
        if dictionary == None:
            dictionary = dict()
            stopDictionary[dataKey] = dictionary
        return dictionary

    def addDataToHistogram(self, histogram, key):
        histogram[key] = histogram.get(key, 0) + 1


class ReoffsetHandler(webapp2.RequestHandler):
    
    tableTitles = ('tijd', 'aantal', 'perc.')
    tableFormat = (':%02d', '%d', '%.1f%%')

    def get(self):
        series =TASeries.get(self.request.get('series'))
        
        self.doc = ToolsDocument('Herschik offsets serie %s' % series.name)
        self.writeReport(series)
        self.response.out.write(self.doc.write())
    
    def post(self):
        series              = TASeries.get(self.request.get('series'))
        self.deltaOffset    = [int(self.request.get('offset_up')), int(self.request.get('offset_down'))]
        self.round          = [int(self.request.get('round_up')), int(self.request.get('round_down'))]
        self.processedObjects   = []
        self.processedMissions  = {}
        self.processedPoints    = {}
            
        self.doc = ToolsDocument('Aangepaste offsets serie %s' % series.name)
        self.doc.main.add(markup.heading(2, 'Aangepaste pat