
var ini_file = cFos_object.ini_file;
var ini_name = "user.ini";
var def_ini_name = "settings.ini";
var other_name = "Other";
var prio_sec_names = ["", "lowest", "low", "normal", "high", "higher"];
var clean_name = /[\x00-\x1f:<>&"\|\?\*]/g;
var filter_key = is_programs ? "program_filter" : "protocol_filter";
var filters = { };
var prio_items = { };
var current_filter;
var undo_buf = [ ];
var suggest = true;

var filter_trans = { "games": ml_object.games, "file sharing": ml_object.p2p, "p2p": ml_object.p2p, "voice over ip": ml_object.voip,
   "multimedia": ml_object.multimedia, "remote control": ml_object.remote_control, "misc_high": ml_object.misc_high,
   "other": ml_object.other,"clients": ml_object.clients, "servers": ml_object.servers, "special": ml_object.special };

function browse_for_file() {
   var f = cFos_object.open_file_dialog("*.exe\0*.exe\0*.*\0*.*\0", 0);
   if (f != "") $("#exefile")[0].value = f.replace(/^.*\\/, "");
}

function send_prio_to_cfos(exe, desc) {
   try {
      var h = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
      h.Option(0) = "add_prio_dialog"; // user agent
      var url = "http://www.cfos.de/cgi-bin/priopost.pl"
         + "?program=" + encodeURIComponent(exe)
         + "&program_name=" + encodeURIComponent(desc)
         + "&genre=" + encodeURIComponent(current_filter)
         + "&email=" + encodeURIComponent("dialog@cfos.de");
      h.Open("GET", url, false);
      h.Send();
   }
   catch (x) { }
}

function prio_obj(name, filter, desc, prio, ini_name) {
   return { name: name, filter: filter, desc: desc, prio: prio,
      ini_name: ini_name, tx_limit: "-", action: "",

      make_tr: function() {
         if (this.name.match(clean_name)) alert("Warning: exe_file has illegal characters: " + this.name);
         var n = this.desc + ' (' + this.name + ')';
         var s = '<tr data-name="' + this.name + '"><td class="wrap"><span class="wrap">' + n + '</span></td>'
            + '<td class="slider"><img class="set_prio" src="images/prio_' + this.prio + '.png" alt="'+ prio_names[this.prio] + '"/><span class="smalltext" style="float: right">' + prio_names[this.prio] + '</span></td>'
            + '<td class="button"><img class="button" src="images/settings.png" onmouseover=\'this.src="images/settings_a.png";\' onmouseout=\'this.src="images/settings.png";\' title="' + ml_object.settings + '" alt="' + ml_object.settings + '"/></td>';
         if (is_programs) s += '<td class="button"><img class="button" src="images/delete.png" onmouseover=\'this.src="images/delete_a.png";\' onmouseout=\'this.src="images/delete.png";\' title="' + ml_object._delete + '" alt="' + ml_object._delete + '"/></td>';
         s += '</tr>';
         return s;
      },

      add_undo: function(action) {
         var n = jQuery.extend(true, n, this);   // make deep copy
         n.action = action;
         var skip = undo_buf.length > 0 && n.name == undo_buf[undo_buf.length-1].name
            && n.action == "mod" && undo_buf[undo_buf.length-1].action == "mod";
         if (!skip) undo_buf.push(n);
         $("#undo").removeAttr('disabled');
         $("#restore").removeAttr('disabled');
         return this;
      },
      store: function() {
         prio_items[this.name] = this;
         var val = this.filter + "," + this.desc;
         ini_file.set(this.ini_name, prio_sec_names[this.prio], this.name, val);
         ini_file.flush();
         cFos_object.action("spd reload");
         return this;
      },
      del: function() {
         ini_file.del(this.ini_name, prio_sec_names[this.prio], this.name);
         ini_file.flush();
         cFos_object.action("spd reload");
         delete prio_items[this.name];
         return null;
      },
      add_to_table: function() {
         var el = this.make_tr();
         var r = $("#tablebox table tbody tr");
         var n = this.desc + ' (' + this.name + ')';
         for (var i=0; i < r.length; ++i) {
            var p2 = prio_items[$(r[i]).attr("data-name")];
            if (n.toLowerCase() < (p2.desc + ' (' + p2.name + ')').toLowerCase()) {
               $(el).insertBefore($(r[i])).scrollIntoView();
               return;
            }
         }
         if(r.length > 0) $(el).insertAfter($(r[r.length-1])).scrollIntoView();
         else $("#tablebox table tbody").append(el).scrollIntoView();
         return this;
      },
      set_limit: function(val, dir) {
         val = jQuery.trim(val);
         var m, type = is_programs ? "prog" : "l7-prot";
         if (val == "" || val == "-") {
            cFos_object.spd_command('@limit class -D c_' + type + '_' + this.name.replace(/ /g, "/"));
            this[dir+"_limit"] = "-";
         }
         else if (m = val.match(/(\d+)(%?)/)) {
            if (m[2]) val = Math.min(100, parseInt(m[1])) + "%";
            cFos_object.spd_command('@limit class c_' + type + '_' + this.name.replace(/ /g, "/") + ' -speed ' + val);
            if (this[dir+"_limit"] == "-") {
               cFos_object.spd_command('@limit filter -A -' + dir + ' -' + type + ' "' + this.name + '" -c c_' + type + '_'
                  + this.name.replace(/ /g, "/"));
            }
            this[dir+"_limit"] = val;
         }
      }
   };
}

function undo() {
   if (undo_buf.length == 0) return;
   var p = undo_buf.pop();
   if (undo_buf.length == 0) $("#undo").attr('disabled', true);
   if (current_filter != p.filter) set_filter(p.filter);
   if (p.action == "del") {
      var r = find_row_by_name(p.name);
      $(r).remove();
      p.del();
   }
   else if (p.action == "add") p.store().add_to_table();
   else if (p.action == "mod") {
      var r = find_row_by_name(p.name);
      $(r).remove();
      prio_items[p.name].del();
      p.store().add_to_table();
   }
}

function find_row_by_name(name) {
   var r = $("#tablebox table tbody tr");
   for (var i=0; i < r.length; ++i)
      if ($(r[i]).attr("data-name") == name) return r[i];
   return null;
}

function delete_prio(r) {
   var name = $(r).attr("data-name");
   var p = prio_items[name];
   p.add_undo("add").del();
   var r = find_row_by_name(p.name);
   $(r).remove();
}

function change_prio(r, e) {
   var name = $(r).attr("data-name");
   var p = prio_items[name];
   var prio = show_prio(e.pageX);
   if (prio == p.prio) return;
   p.add_undo("mod");
   if (p.ini_name == ini_name) p.del();   // don't delete from system.ini
   p.prio = prio; p.ini_name = ini_name;  // switch to user.ini
   p.store();
}

function change_settings() {
   var e = $('#settings_box');
   var name = e.attr("data-name");
   var p = prio_items[name];
   p.add_undo("mod");
   p.set_limit($("#tx_limit")[0].value, "tx");
   e.hide();
}

function handle_mouse_up(e) {
   if (clicked_el.tagName.toLowerCase() != "img") return true;
   var r = clicked_el;
   while (r.tagName.toLowerCase() != "tr") r = $(r).parent()[0];
   if (clicked_el.src.indexOf("settings") != -1) {
      var name = $(r).attr("data-name");
      $("#tx_limit")[0].value = prio_items[name].tx_limit || "-";
      $('#settings_box').attr("data-name", name).show().css('zIndex', 1).center();

   }
   else if (clicked_el.src.indexOf("delete") != -1) delete_prio(r);
   else if (clicked_el.src.indexOf("prio_") != -1) change_prio(r, e);
   return false;
}

function start_events() {
   $("#tablebox").on(mouse_evt_obj, null, { mouse_up_handler: handle_mouse_up })
      .on("mouseenter", "img.set_prio", function(e) {
         $("#help_prio").show();
         e.target.src = e.target.src.replace(/(\d)\./, "$1_a.");
      })
      .on("mouseleave", "img.set_prio", function(e) {
         $("#help_prio").hide();
         e.target.src = e.target.src.replace("_a.", ".");
      })
}

function add_np_mouse_up(e) {
   if (clicked_el.tagName.toLowerCase() != "img") return true;
   if (clicked_el.src.indexOf("checkbox_") != -1) {
      suggest = !suggest;
      $("#suggest_prog")[0].src = suggest ? "images/checkbox_on.png" : "images/checkbox_off.png";
      return false;
   }
   else if (clicked_el.src.indexOf("prio_") != -1) {
      var prio = show_prio(e.pageX);
      $('#new_program_box').attr('data-prio', prio);
      return false;
   }
   return true;
}

function add_new_program() {
   var desc = jQuery.trim($("#desc")[0].value);
   var exe = $("#exefile")[0].value;
   var idx = exe.lastIndexOf('\\');
   if (idx != -1) exe = exe.substr(idx+1);
   if (exe.charAt(1) == ':') exe = exe.substr(2);
   exe = exe.replace(clean_name, "");
   exe = jQuery.trim(exe);
   if (exe == "") return;
   var exists = exe in prio_items;
   if (exists) {
      var s = ml_object.overwrite.replace(/#p/, exe);
      if (!confirm(s)) return;
   }
   var prio = $('#new_program_box').attr('data-prio');
   if (suggest && !exists) send_prio_to_cfos(exe, desc);
   var p = prio_obj(exe, current_filter, desc, prio, ini_name);
   if (exists) {
      var r = find_row_by_name(exe);
      $(r).remove();
      prio_items[exe].add_undo("mod").del();
      p.store().add_to_table();
   }
   else p.add_undo("del").store().add_to_table();
   hide_new_program_box();
}

function show_new_program_box() {
   $('#new_program_box').show().css('zIndex', 1).center().on(mouse_evt_obj, null, { mouse_up_handler: add_np_mouse_up });
}
function hide_new_program_box() {
   $('#new_program_box').hide().off(mouse_evt_obj);
}

var sec_el_match = new RegExp("\\s*([\\w\\s]*)\\s*,\\s*(.*)\\s*");

function read_section(iname, prio) {
   var sec_name = prio_sec_names[prio];
   ini_file.open(iname, sec_name);
   var s = JSON.parse(ini_file.section_as_json);
   var cnt = s.k.length;
   for (var i=0; i < cnt; ++i) {
      var key = s.k[i];
      var val = s.v[i];
      var m = val.match(sec_el_match);
      var filter = "", desc = "";
      if (m != null) {
         filter = m[1];
         desc = m[2];
      }
      if (filter == "") filter = other_name;
      filters[filter] = true;
      if (key in prio_items && prio_items[key].ini_name == iname) alert("warning: duplicate " + key + " in "
         + prio_names[prio_items[key].prio] + "/" + prio_names[prio]);
      prio_items[key] = prio_obj(key, filter, desc, prio, iname);
   }
}

function load_table() {
   var a = [];
   for (var x in prio_items) {
      var p = prio_items[x];
      if (p.filter != current_filter) continue;
      var disp_name = p.desc.length != 0 ? p.desc + " (" + x + ")" : x;
      a.push({ disp_name: disp_name, p: p});
   }
   a.sort(function(l, r) {
      var l = l.disp_name.toLowerCase(), r = r.disp_name.toLowerCase();
      if (l < r) return -1;
      if (l > r) return 1;
      return 0;
   });
   $("#tablebox table tbody").children().remove();
   var s = "";
   for (var i=0; i < a.length; ++i) s+= a[i].p.make_tr();
   $("#tablebox").html('<table class="list"><tbody>' + s + '</tbody></table>');
   $("#tablebox table").attr("summary", ml_object.entries);
}

function set_filter(filter) {
   var reload = current_filter != filter;
   current_filter = filter;
   cFos_object.param(filter_key) = current_filter;
   if (reload) load_table();
   $('li').removeClass('active');
   $('li[id=' + current_filter.replace(/\W/g, "_") + ']').addClass('active');
}

function restore_defaults(prog) {
   modified = false;
   cFos_object.restore_defaults(prog);
   cFos_object.action("spd reload");
   window.location.reload();
}

function resize_divs() {
   var win_height = $(window).height();
   $('#menu').height(win_height);
   $('#tablebox').height(win_height - $('#top').height() - 128);
}

function dialog() {
   for (var i=1; i < 6; ++i) prio_sec_names[i] += is_programs ? "progs" : "prots";

   for (var i=1; i < 6; ++i) read_section(def_ini_name, i);
   for (var i=1; i < 6; ++i) read_section(ini_name, i);
//   if (!filters.other_name) filters[other_name] = true;

   var limit_class_list = cFos_object.spd_command("@limit class").split("\n");
   for (var l in limit_class_list) {
      var limit_class = limit_class_list[l];
      if (limit_class.indexOf("limit class c_prog_") != -1) {
         var name = limit_class.substr(19, limit_class.indexOf("-speed")-20);
         name = name.replace(/\//g, " ");
         if (name in prio_items) prio_items[name].tx_limit = limit_class.substr(limit_class.indexOf("-speed")+7);
      }
   }

   if (is_programs) $("#add_new_program").show();
   resize_divs();

   // make submenu
   for (var x in filters) {
      var s = '<li class="sub" id="' + x.replace(/\W/g, "_") + '"><a href="javascript:set_filter(\'' + x + '\')">'
         + (filter_trans[x.toLowerCase()] || x) + '</a></li>';
      if (is_programs) $('#li_prog').append(s); else $('#li_prot').append(s);
   }

   current_filter = cFos_object.param(filter_key);
   if (!(current_filter in filters)) for (current_filter in filters) break;
   set_filter(current_filter);

   load_table();
   start_events();
}

window.onresize = resize_divs;

