// class.MonsterState.js
//
// dependencies:
// - class.MonsterCounty.js
// - class.MonsterRoute.js

var MonsterUtil,
    MonsterCounty, MonsterCountyFromJSON,
    MonsterRoute, MonsterRouteFromJSON;

function MonsterState(index, id, name, abbr, opts) {
  opts = $.extend({
    counties : [],
    routes : []
  }, opts);

  // required attributes
  this.index = index;
  this.id = id;
  this.name = name;
  this.abbr = abbr;

  // optional attributes
  this.counties = opts.counties;
  this.routes = opts.routes;

  // generated attributes
  this.var_path = 'states['+this.index+']';

  // setup
  for (var i = 0; i < this.counties.length; i++) {
    if (this.counties[i].constructor != MonsterCounty) {
      try {
        this.counties[i] = MonsterCountyFromJSON(this.counties[i]);
      } catch (e) {
        this.counties.splice(i, 1);
      }
    }
  }

  for (var i = 0; i < this.routes.length; i++) {
    if (this.routes[i].constructor != MonsterRoute) {
      try {
        this.routes[i] = MonsterRouteFromJSON(this.routes[i]);
      } catch (e) {
        this.routes.splice(i, 1);
      }
    }
  }
}

MonsterState.prototype.getCities = function () {
  var cities = [];

  for (var i = 0; i < counties.length; i++) {
    var county = counties[i];

    for (var j = 0; j < county.cities.length; j++) {
      cities.push(county.cities[i]);
    }
  }

  return cities;
};

MonsterState.prototype.addCounty = function (county) {
  if (county.constructor == MonsterCounty) {
    if (county.index < 0) {
      county.setIndex(this.counties.length);
    }

    this.counties.push(county);
  }
};

MonsterState.prototype.addCountyJSON = function (county) {
  try {
    this.addCounty(MonsterCountyFromJSON(county));
  } catch (e) {
    return;
  }
};

MonsterState.prototype.addCounties = function (counties) {
  for (var i = 0; i < counties.length; i++) {
    this.addCounty(counties[i]);
  }
};

MonsterState.prototype.addCountiesJSON = function (counties) {
  for (var i = 0; i < counties.length; i++) {
    this.addCountyJSON(counties[i]);
  }
};

MonsterState.prototype.addRoute = function (route) {
  if (route.constructor == MonsterRoute) {
    if (route.index < 0) {
      route.setIndex(this.routes.length);
    }

    this.routes.push(route);
  }
}

MonsterState.prototype.addRouteJSON = function (route) {
  try {
    this.addRoute(MonsterRouteFromJSON(route));
  } catch (e) {
    return;
  }
}

MonsterState.prototype.addRoutes = function (routes) {
  for (var i = 0; i < routes.length; i++) {
    this.addRoute(routes[i]);
  }
};

MonsterState.prototype.addRoutesJSON = function (routes) {
  for (var i = 0; i < routes.length; i++) {
    this.addRouteJSON(routes[i]);
  }
}

MonsterState.prototype.toString = function (html) {
  if (html) {
    return '<h3 class="MarginTopTen">'+this.name+'</h3>';
  } else {
    return this.name;
  }
};

var MonsterStateFromJSON = function (state) {
  if (state.constructor == Array) {
    var states = [];
    for (var i = 0; i < state.length; i++) {
      try {
        states.push(MonsterStateFromJSON(state[i]));
      } catch (e) {
        continue;
      }
    }

    return states;
  } else if (state.constructor == Object) {
    if (!( // check required fields
        typeof state.index == 'number' &&
        typeof state.id == 'number' &&
        typeof state.name == 'string' &&
        typeof state.abbr == 'string')) {
      throw 'Missing required field. Must contain id, name, and abbr.';
    }
  
    var opts = MonsterUtil.getOpts(state, {
      counties : Array,
      routes : Array
    });

    try {
      if (state.index < 0) {
        state = new MonsterState(
          states.length,
          state.id,
          state.name,
          state.abbr,
          opts
        );
        states.push(state);
      } else {
        state = new MonsterState(
          state.index,
          state.id,
          state.name,
          state.abbr,
          opts
        );
      }
    } catch (e) {
      throw 'Failed to instantiate State. '+e;
    }
    
    return state;
  } else if (state.constructor == MonsterState) {
    return state;
  } else {
    throw 'Invalid state parameter provided.';
  }
};