// constant changes for the scoring
var STR_TABLE_MODS = {
  id_155 : {  // Arminia Bielefeld
//        delta : -4,
   // mark : "*"
  }
}

// get the real table compared to the table from the last playday.
function str_get_real_table (mday) {
  var table = str_get_table(STR_FIXTURES_STATIC, mday);

  // compare with last playdays table
  var table_last = str_get_table(STR_FIXTURES_STATIC, mday-1);

  if (table_last.length > 0) {
    // first get the last positions
    var rank = 0;
    var last_rank = {};
    for (var i=0; i < table_last.length; i++) {
      for (var j=0; j < table_last[i].length; j++) {
        last_rank[table_last[i][j].oti] = rank + 1;
      }
      rank += table_last[i].length;
    }

    // now set this information on the new table.
    for (var i=0; i < table.length; i++) {
      for (var j=0; j< table[i].length; j++) {
        table[i][j].last = last_rank[table[i][j].oti];
      }
    }
  }

  return table;
}

// get the own table compared to the current real table
function str_get_my_table (mday) {
  var table = str_get_table(STR_FIXTURES, mday);

  // compare with last playdays table
  var real_table = str_get_table(STR_FIXTURES_STATIC, mday);

  if (real_table.length > 0) {
    // first get the last positions
    var rank = 0;
    var last_rank = {};
    for (var i=0; i < real_table.length; i++) {
      for (var j=0; j < real_table[i].length; j++) {
        last_rank[real_table[i][j].oti] = rank + 1;
      }
      rank += real_table[i].length;
    }

    // now set this information on the new table.
    for (var i=0; i < table.length; i++) {
      for (var j=0; j< table[i].length; j++) {
        table[i][j].last = last_rank[table[i][j].oti];
      }
    }
  }

  return table;
}

// returns a list of lists with team-infos. teams which can not be positioned
// are in the same list (sharing the same position!).
function str_get_table (fix, mday) {

  // create a fixture-array which is limited to the given mday
  var mday_fix = {};
  for (var omi in fix) {
    // ignore matches after mday
    if (fix[omi].mday > mday) {
      continue;
    }
    mday_fix[omi] = fix[omi];
  }

  // get initial data
  var data_sums = str_calculate_sums(mday_fix, 0);

  // now create the first version of the table. sorted by score, difference and
  // goal (0) 1) and 2)).
  var table = str_sort_initial(data_sums);

  // if there still are undecided positions, sort them by direct goal
  // difference (3))
  if (table.length < 18) {
    table = str_direct_goal_difference(table, mday_fix);
  }

  // still undecided? sort by away goals in the direct comparison (4))
  if (table.length < 18) {
    table = str_direct_away_goals(table, mday_fix);
  }

  // yet undecided? sort by all away goals (5))
  if (table.length < 18) {
    table = str_all_away_goals(table, mday_fix);
  }

  // if there are still undecided positions, this might be conflicts with more
  // than 2 teams. In that case we have to create small tables to try to
  // resolve the conflicts.
  if (table.length < 18) {
    table = str_small_tables(table, mday_fix);
  }

  // if we can't decide it now, we just sort them alphanumerical (6))
  if (table.length < 18) {
    table = str_sort_alphanumeric(table);
  }

  return table;
}

// ------------------------------------------------------------------------
// below this point all functions expect the fixture fix to be limited to the
// data up to the given match-day. All Informationen in fix will be used for
// the calculations.

// calculate the sums up to the given mday
function str_calculate_sums (fix, ignoredelta) {
  // initialize with the fixtures data
  var table_info = str_get_table_info (fix);

  // calculate sums
  var result = {};

  // should we ignore deltas in the score?
  if (ignoredelta == undefined) {
    ignoredelta = 0;
  }

  for (var matchday in table_info) {
    for (var oti in table_info[matchday]) {
      var keyname = "oti_"+oti;
      if (result[keyname] == undefined) {

        var delta = 0;
        if (!ignoredelta && STR_TABLE_MODS["id_"+oti] != undefined && STR_TABLE_MODS["id_"+oti].delta != undefined) {
          delta = STR_TABLE_MODS["id_"+oti].delta;
        }
        result[keyname] = {
          "score"  : delta,
          "diff"   : 0,
          "goals"  : [0,0],
          "played" : 0,
          "oti"    : oti,
          "name"   : table_info[matchday][oti].name,
          "longname" : table_info[matchday][oti].longname.toLowerCase()
        };
      }
      // longnames are only used to sort the entries

      result[keyname].score    += table_info[matchday][oti].score;
      result[keyname].diff     += table_info[matchday][oti].diff;
      result[keyname].goals[0] += parseInt(table_info[matchday][oti].goals[0]);
      result[keyname].goals[1] += parseInt(table_info[matchday][oti].goals[1]);

      if (table_info[matchday][oti].played) {
        result[keyname].played++;
      }
    }
  }

  return result;
}

// get the data from the fixture-array into a somehow better format.
// fix has to be limited to the wanted mday.
function str_get_table_info (fix) {
  var result = [];

  var goals;
  var score_home;
  var score_away;

  // traverse all the matches
  for (var omi in fix) {

    // init result for current mday if needed
    if (result[fix[omi].mday] == null) {
      result[fix[omi].mday] = {};
    }

    // build goal array: "n:m" => [n,m]
    goals = fix[omi].goals.split(":");

    // we assume that current games is already over
    var played = true;

    // score is something like "-:-"?
    if ((isNaN(goals[0])) || (isNaN(goals[1]))) {

      // current match has not started
      played = false;

      // interpretate "-" as 0
      goals[0] = 0;
      goals[1] = 0;
      score_home = 0;
      score_away = 0;

    } else {

      if (parseInt(goals[0]) > parseInt(goals[1])) {
        // home won
        score_home = 3;
        score_away = 0;

      } else if (parseInt(goals[0]) < parseInt(goals[1])) {
        // away won
        score_home = 0;
        score_away = 3;

      } else {
        // stale mate
        score_home = 1;
        score_away = 1;
      }
    }

    // assign home team
    result[fix[omi].mday][fix[omi].homeoti] = {
      "score"    : score_home,
      "diff"     : goals[0] - goals[1],
      "goals"    : goals,
      "played"   : played,
      "name"     : fix[omi].home,
      "longname" : fix[omi].longhome
    };

    // assign away team
    result[fix[omi].mday][fix[omi].awayoti] = {
      "score"    : score_away,
      "diff"     : goals[1] - goals[0],
      "goals"    : [goals[1], goals[0]],
      "played"   : played,
      "name"     : fix[omi].away,
      "longname" : fix[omi].longaway
    };
  }

  return result;
}

// uses the given sums to create the first version of the table. this already
// works most of the time. returns a list of lists. teams which have the same
// position in the table are together in one list (this is called a conflict).
function str_sort_initial (data_sums) {

  var list = null;
  for (var oti in data_sums) {
    // use a binary tree to sort the list using the given criteria.
    list = list_add(list, data_sums[oti], [data_sums[oti].score, data_sums[oti].diff, data_sums[oti].goals[0]]);
  }

  return list_to_array_asc(list);
}

// recreate the given table but try to resolve conflicts by using the direct
// goal difference
function str_direct_goal_difference (table, fix) {
  var new_table = [];

  for (var i = 0; i < table.length; i++) {
    if (table[i].length == 2) {
      var matches = str_get_matches([table[i][0].oti, table[i][1].oti], fix);
      if (matches.length != 2) {
        // this only applies, if already two matches have bin played.
        new_table.push(table[i]);

      } else {
        // get the direct difference
        var difference = 0;

        // gather away goals
        for (var j=0; j<matches.length; j++) {
          var goals = matches[j].goals.split(":");
          if (matches[j].homeoti == table[i][0].oti) {
            difference += goals[0] - goals[1];

          } else {
            difference += goals[1] - goals[0];
          }
        }

        // order is ok
        if (difference > 0) {
          new_table.push([table[i][0]]);
          new_table.push([table[i][1]]);

        } else if (difference < 0) {
          // swap
          new_table.push([table[i][1]]);
          new_table.push([table[i][0]]);

        } else {
          new_table.push(table[i]);
        }
      }

    } else {
      new_table.push(table[i]);
    }
  }

  return new_table;
}

// recreate the given table but try to resolve conflicts by using the direct
// away goals. Only if two teams are on the same rank.
function str_direct_away_goals (table, fix) {
  var new_table = [];

  for (var i = 0; i < table.length; i++) {
    if (table[i].length == 2) {
      var matches = str_get_matches([table[i][0].oti, table[i][1].oti], fix);
      if (matches.length != 2) {
        // this only applies, if already two matches have bin played.
        new_table.push(table[i]);

      } else {
        // get the away goals
        var agoals = {};

        // init away goals
        agoals["id"+table[i][0].oti] = 0;
        agoals["id"+table[i][1].oti] = 0;

        // gather away goals
        for (var j=0; j<matches.length; j++) {
            agoals["id"+matches[j].awayoti] = matches[j].goals.split(":")[1];
        }

        // order is ok
        if (agoals["id"+table[i][0].oti] > agoals["id"+table[i][1].oti]) {
          new_table.push([table[i][0]]);
          new_table.push([table[i][1]]);

        } else if (agoals["id"+table[i][0].oti] < agoals["id"+table[i][1].oti]) {
          // swap
          new_table.push([table[i][1]]);
          new_table.push([table[i][0]]);

        } else {
          new_table.push(table[i]);
        }
      }

    } else {
      new_table.push(table[i]);
    }
  }

  return new_table;
}

// recreate the given table but try to resolve conflicts by using all away
// goals. Only if two teams are on the same rank.
function str_all_away_goals (table, fix) {
  var new_table = [];

  for (var i = 0; i < table.length; i++) {
    if (table[i].length == 2) {
      var matches = str_get_matches([table[i][0].oti, table[i][1].oti], fix);
      if (matches.length != 2) {
        // this only applies, if already two matches have bin played.
        new_table.push(table[i]);

      } else {
        // get all away goals
        var agoals = {};

        // init away goals
        agoals["id"+table[i][0].oti] = 0;
        agoals["id"+table[i][1].oti] = 0;

        for (var omi in fix) {
          if (fix[omi].goals == "-:-") {
            continue;
          }
          for (var j=0; j<table[i].length; j++) {
            if (fix[omi].awayoti == table[i][j].oti) {
              agoals["id"+table[i][j].oti] += parseInt(fix[omi].goals.split(":")[1]);
            }
          }
        }

        // order is ok
        if (agoals["id"+table[i][0].oti] > agoals["id"+table[i][1].oti]) {
          new_table.push([table[i][0]]);
          new_table.push([table[i][1]]);

        } else if (agoals["id"+table[i][0].oti] < agoals["id"+table[i][1].oti]) {
          // swap
          new_table.push([table[i][1]]);
          new_table.push([table[i][0]]);

        } else {
          new_table.push(table[i]);
        }
      }

    } else {
      new_table.push(table[i]);
    }
  }

  return new_table;
}

// recreate the given table and try to resolve conflicts if more then two teams
// are on the same position.
function str_small_tables (table, fix) {
  var new_table = [];

  for (var i = 0; i < table.length; i++) {
    if (table[i].length > 2) {
      // which teams are there to compare.
      var otis = [];
      for (var j = 0; j<table[i].length; j++) {
        otis.push(table[i][j].oti);
      }
      // get the played matches
      var omis = str_get_omis(otis, fix);
      if (omis.length < (otis.length*(otis.length - 1))) {
        // not all matches are played yet!
        new_table.push(table[i]);
      }

      // we create a small version of the data for a table consisting only of
      // the data for the teams on this position.
      var small_fix = {};
      for (var j = 0; j < omis.length; j++) {
        small_fix[omis[j]] = fix[omis[j]];
      }
      var data_sums = str_calculate_sums(small_fix, 1);
      var small_table = str_sort_initial(data_sums);
      for (var j = 0; j < small_table; j++) {
        new_table.push(small_table[j]);
      }

    } else {
      new_table.push(table[i]);
    }
  }

  return new_table;
}

// all remaining conflicts now are order alphanumeric
function str_sort_alphanumeric (table) {

  for (var i = 0; i < table.length; i++) {
    if (table[i].length > 1) {
      table[i].sort(str_compare_table_entries);
    }
  }

  return table;
}

// return all the matches where the given teams have played in a list.
function str_get_matches (teams, fix) {
  var matches = [];

  var omis = str_get_omis(teams, fix);
  for (var i = 0; i < omis.length; i++) {
    matches.push(fix[omis[i]]);
  }

  return matches;
}

// return all omis of the matches played by the given teams in the list.
function str_get_omis (teams, fix) {
  var omis = [];

  for (var omi in fix) {
    if (fix[omi].goals == '-:-') {
      continue;
    }
    var found = 0;
    for (var i = 0; i < teams.length; i++) {
      if (fix[omi].homeoti == teams[i] || fix[omi].awayoti == teams[i]) {
        found++;
      }
    }
    // found a match with at least two of the searched teams in?
    if (found == 2) {
      omis.push(omi);
    }
  }

  return omis;
}

// used to sort the entries alphanumerical regarding to the longname.
function str_compare_table_entries(a, b) {
  if (a.longname > b.longname) {
    return 1;
  } else if (a.longname < b.longname) {
    return -1;
  }
  return 0;
}
