# Code for the Route class
#
# Copyright (C) 1996-2001 Chris Lawrence
# This file may be freely distributed under the terms of the RoutePlanner
# license.  A copy should appear as 'LICENSE' in the archive that this
# file was included in.

import string, rpunits, bisect
from rpunits import UNITS_METRIC

class Route:
    def __init__(self, data=None, cities=None):
        if data and cities:
            citynames = data[0:2]
            self.exits = data[5:7]
            # Lower city name comes first; this will help provide a
            # uniform file format for patching
            if string.lower(citynames[0]) > string.lower(citynames[1]):
                citynames.reverse()
                self.exits.reverse()
            
            stuff = string.split(data[2])
            self.distance = rpunits.Distance(float(stuff[0]), stuff[1])
            self.i_distance = float(self.distance.AsUnit(UNITS_METRIC))
            self.speed = int(data[3])
            self.speedcode = int(data[4])

            self.time = None
            if self.speedcode == 0:
                self.time = 60.0 * stuff[0] / self.speed
            elif self.speedcode == 1:
                self.time = self.speed
            
            if self.speedcode == 10:
                self.speedcode = 2
                if stuff[1] == UNITS_METRIC:
                    self.speed = -16
                else:
                    self.speed = -10

            self.name = data[7]
            if len(data) > 8:
                # Flag extension: either a string or dictionary
                if type(data[8]) == type(''):
                    self.flags = data[8]
                    self.make_flagmap()
                elif type(data[8]) == type({}):
                    self.flagmap = data[8]
                    self.make_flag_string()
            else:
                self.flags = ''
                self.flagmap = {}
            
            self.city = [ cities[citynames[0]][0], cities[citynames[1]][0] ]

            bisect.insort(self.city[0].roads, (self, 0, self.city[1]) )
            bisect.insort(self.city[1].roads, (self, 1, self.city[0]) )
        else:
            self.city = [None]*2
            self.exits = [None]*2
            self.distance = self.speed = self.speedcode = \
                            self.name = self.flags = None
            self._distance = 0.0

    def __repr__(self):
        x = str(self.city[0])+'|'+str(self.city[1])+'|'+\
            str(self.distance)+'|'+str(self.speed)+'|'+\
            str(self.speedcode)+'|'+self.exits[0]+'|'+self.exits[1]+'|'+\
            self.name
        if self.flags:
            return x+"|"+self.flags
        else:
            return x

    def __str__(self):
        return self.name

    def __cmp__(self, other):
        return ( cmp(self.city[0], other.city[0]) or
                 cmp(self.city[1], other.city[1]) or
                 cmp(self.distance, other.distance) or
                 cmp(string.lower(self.name), string.lower(other.name)) )
    
    def __hash__(self):
        return id(self)

    def __del__(self):
        try:
            if self.city:
                del self.city
        except:
            pass

    def make_flagmap(self):
        self.flagmap = {}
        bits = string.split(self.flags, ',')
        for bit in bits:
            if bit == 'ferry' or bit == 'toll' or bit == 'scenic':
                self.flagmap[bit] = 1
            elif bit[:7] == 'height=':
                # Height restriction
                self.flagmap['height'] = float(bit[7:])

    def make_flag_string(self):
        flags = []
        for flag, value in self.flagmap.items():
            if flag != 'height':
                if value:
                    flags.append(flag)
            else:
                flags.append('%s=%.2f' % value)
        self.flags = string.join(flags, ',')
# End of Route
