// class.MonsterRoute.js
//
// dependencies
// - class.MonsterCity.js

var MonsterUtil,
    MonsterCity, MonsterCityFromJSON,
    MonsterCounty, MonsterCountyFind, MonsterCountyFromJSON,
    MonsterState, MonsterStateFromJSON;

function MonsterRoute(index, db_id, state, name, desc, long_desc, points, levels, opts) {
  opts = $.extend({
    cities        : [],
    color         : '#0000FF',
    hover_color   : '#000000',
    highways      : null,
    newline       : false,
    num_levels    : 18,
    opacity       : 0.3,
    hover_opacity : 0.7,
    weight        : 4,
    zoom_factor   : 2
  }, opts);

  // required attributes
  this.index = index;
  this.db_id = db_id;
  this.state = state;
  this.name = name;
  this.desc = desc;
  this.long_desc = long_desc;
  this.points = points;
  this.levels = levels;

  // optional attributes
  this.cities = opts.cities;
  this.color = opts.color;
  this.hover_color = opts.hover_color;
  this.highways = opts.highways;
  this.newline = opts.newline;
  this.num_levels = opts.num_levels;
  this.opacity = opts.opacity;
  this.hover_opacity = opts.hover_opacity;
  this.weight = opts.weight;
  this.zoom_factor = opts.zoom_factor;

  // generated attributes
  this.line = new GPolyline.fromEncoded({
    color: this.color,
    levels: this.levels,
    numLevels: this.num_levels,
    opacity: this.opacity,
    points: this.points,
    weight: this.weight,
    zoomFactor: this.zoom_factor
  });
  this.zoom = MonsterUtil.zoom;
  this.bounds = this.line.getBounds();
  this.center = this.bounds.getCenter();
  this.ne = this.bounds.getNorthEast();
  this.sw = this.bounds.getSouthWest();

  // setup
  this.get_started = false;
  if (this.state && this.state.constructor != MonsterState) {
    try {
      this.state = MonsterStateFromJSON(this.state);
      this.state.addRoute(this);
    } catch (e) {
      throw 'Required state field invalid. ' + e;
    }
  }

  this.setIndex(this.index);
}

// init()
// adds this route to the map
MonsterRoute.prototype.init = function (single) {
  this.zoom = MonsterUtil.map.getBoundsZoomLevel(this.line.getBounds());

  MonsterUtil.map.addOverlay(this.line);

  var route = this;
  if (single) { // || routes.length == 1
    this.line.setStrokeStyle({
      color:this.hover_color,
      opacity:this.hover_opacity
    });
    MonsterUtil.map.setCenter(this.center, this.zoom);

    if (!this.cities.length) {
      this.getCities();
    } else {
      this.showCities();
    }
  } else {
    GEvent.addListener(this.line, 'mouseover', function(latlng) {
      $('#'+route.id).addClass('hover');
      this.setStrokeStyle({
        color   : route.hover_color,
        opacity : route.hover_opacity
      });
    });
    GEvent.addListener(this.line, 'mouseout', function(latlng) {
      $('#'+route.id).removeClass('hover');
      this.setStrokeStyle({
        color   : route.color,
        opacity : route.opacity
      });
    });
    GEvent.addListener(this.line, 'click', function(latlng) {
      route.go();/*
      MonsterUtil.map.openInfoWindow(latlng, route.desc + (!single ?
        '<p class="MarginTopTwenty">'
        +'<a class="FontEightyFive" href="'+route.url+'">'
          +'<span class="Icon IconBuilding"></span>'
          +'View cities along '+route.name+' &raquo;</a></p>' : '')); */
    });
  }
  GEvent.trigger(this.line, 'mouseout');
};

// show()
// displays single route, long description, and jobs along the route
MonsterRoute.prototype.show = function () {
  MonsterUtil.map.clearOverlays();
  this.init(true);
  $('#LongRouteDesc').slideDown().html(this.toString());
  //$('#LongRouteDesc').slideDown().html(this.long_desc);
  $('#showRouteJobs').slideDown();
};

MonsterRoute.prototype.go = function () {
  window.location.href = this.url;
};

MonsterRoute.prototype.setIndex = function (index) {
  this.index = index;
  this.id = this.state.name+'_'+this.index+'_route';
  this.url = MonsterUtil.getBaseURL()+'commute/index.html?rt='
    +this.state.index+'_'+this.index;
  this.var_path = this.state.var_path+'.routes['+this.index+']';
};

MonsterRoute.prototype.addLink = function (container) {
  if (!$('#'+this.id).length) {
    var route = this;
    $(container).append(
      '<a id="'+this.id+'" class="Column OneHalf" href="'+this.url+'" '
        +'title="'+this.desc+'">'
        +this.name+(
          this.highways
          ? (this.newline ? '<br />' : ' ')+'('+this.highways+')'
          : '')+'</a>'
    ).find('#'+this.id).mouseover(function(){
      GEvent.trigger(route.line, 'mouseover');
    }).mouseout(function(){
      GEvent.trigger(route.line, 'mouseout');
    });
  }
};

MonsterRoute.prototype.addCity = MonsterUtil.addCity;

MonsterRoute.prototype.addCityJSON = function (city) {
  try {
    if (!city) {
      return;
    } else if (!city.county && city.db_id) {
      city.county = MonsterCountyFind(db_id);
    }

    city.index = this.cities.length;
    this.addCity(MonsterCityFromJSON(city));
  } catch (e) {
    return;
  }
};

MonsterRoute.prototype.addCities = MonsterUtil.addCities;

MonsterRoute.prototype.addCitiesJSON = function (cities) {
  for (var i = 0; i < cities.length; i++) {
    if ((!cities[i].county || cities[i].county.constructor != MonsterCounty) &&
        cities[i].countyID) {
      cities[i].county = MonsterCountyFind(cities[i].countyID);
    }

    this.addCityJSON(cities[i]);
  }
};

MonsterRoute.prototype.getCities = function () {
  MonsterUtil.getScript(
    'getCitiesWithinRoute',
    [this.db_id, this.var_path+'.getCitiesCallback']
  );
  this.get_started = true;
};

MonsterRoute.prototype.showCities = function (force) {
  if (!this.cities.length
      && !this.get_started) {
    this.getCities();
  }

  if (force) {
    $('#showRouteJobs a').remove();
  }

  for (var i = 0; i < this.cities.length; i++) {
    this.cities[i].init();
    this.cities[i].addLink('#showRouteJobs');
  }

  this.get_started = false;
};

MonsterRoute.prototype.getCitiesCallback = MonsterUtil.getCitiesCallback;

MonsterRoute.prototype.toString = function () {
  return this.desc+(this.highways ? ' ('+this.highways+')' : '');
};

/* not in use
MonsterRoute.prototype.getJobs = MonsterUtil.getJobs;
MonsterRoute.prototype.showJobs = MonsterUtil.showJobs;
*/

var MonsterRouteFromJSON = function (route) {
  if (!route) {
    throw 'Invalid route parameter provided.';
  } else if (route.constructor == Array) {
    var routes = [];
    for (var i = 0; i < route.length; i++) {
      try {
        routes.push(MonsterRouteFromJSON(route[i]));
      } catch (e) {
        continue;
      }
    }

    return routes;
  } else if (route.constructor == Object) {
    if (!( // check required fields
        typeof route.index != 'number' &&
        typeof route.state != 'object' &&
        typeof route.name != 'string' &&
        typeof route.desc != 'string' &&
        typeof route.long_desc != 'string' &&
        typeof route.points != 'string'&&
        typeof route.levels != 'string')) {
      throw 'Missing required field. Must contain index, state, name, desc, '
        + 'long_desc, points, and levels.';
    }

    if (route.state.constructor != MonsterState) {
      try {
        route.state = MonsterStateFromJSON(route.state);
      } catch (e) {
        throw 'Required state field invalid. ' + e;
      }
    }

    var opts = MonsterUtil.getOpts(route, {
      cities : Array,
      jobs : Array,
      color : String,
      num_levels : Number,
      opacity : Number,
      weight : Number,
      zoom_factor : Number
    });

    try {
      if (route.index < 0) {
        route = new MonsterRoute(
          route.state.routes.length,
          route.state,
          route.name,
          route.desc,
          route.long_desc,
          route.points,
          route.levels,
          opts
        );
        route.state.routes.push(route);
      } else {
        route = new MonsterRoute(
          route.index,
          route.state,
          route.name,
          route.desc,
          route.long_desc,
          route.points,
          route.levels,
          opts
        );
      }
    } catch (e) {
      throw 'Failed to instantiate Route. '+e;
    }

    return route;
  } else if (route.constructor == MonsterRoute) {
    return route;
  } else {
    throw 'Invalid route parameter provided.';
  }
};

MonsterRouteSetup = function (route) {
  MonsterUtil.map.clearOverlays();
  MonsterUtil.centerMap();
  $('.countyInfo').hide();
  $('.routeInfo').show();

  var state_index, route_index, route_valid = false

  if (route) {
    var route_split = route.split('_');

    if (route_split.length >= 2) {
      state_index = parseInt(route_split[0]);
      route_index = parseInt(route_split[1]);

      route_valid = (
        typeof state_index == 'number'
        && states[state_index]
        && typeof route_index == 'number'
        && states[state_index].routes
        && states[state_index].routes[route_index]);
    }
  }

  for(var i = 0; i < states.length; i++) {
    var container = $('#routeDiv'+states[i].name);

    if (states[i].routes.length) {
      if (!container.find('a').length) {
        container.append(states[i].toString(true));
      }

      for (var j = 0; j < states[i].routes.length; j++) {
        var route = states[i].routes[j];

        route.addLink(container);

        if (!route_valid) {
          route.init();
        } else if (state_index == i && route_index == j) {
          $('#allRouteInstructions').prependTo('#routeDiv').addClass('FontEightyFive');
          $('#oneRouteInstructions').show();
          route.show();
        }
      }

      if (container.find('a').length) {
        container.append('<br clear="all" />');
      }
    }
  }
};

MonsterRouteFind = function (db_id) {
  for (var i = 0; i < states.length; i++) {
    for (var j = 0; j < states[i].routes.length; j++) {
      var route = states[i].routes[j];

      if (route && route.db_id == db_id) {
        return route;
      }
    }
  }

  return null;
};