function m162_isdigitstring(s) {
  if(typeof s != "string")
    return false;

  for(var i = 0; i < s.length; i++) {
    if(isNaN(parseInt(s.charAt(i))))
      return false;
  }

  return true;
}

function m162_ncsum(a, b) {
  if(!(m162_isdigitstring(a) && m162_isdigitstring(b)))
    return null;

  var span = Math.min(a.length, b.length);
  var r = "";

  for(var i = 0; i < span; i++) {
    var n = "" + (parseInt(a.charAt(i)) + parseInt(b.charAt(i)));
    r += n.charAt(n.length - 1);
  }

  return r;
}

function m162_ncsub(a, b) {
  if(!(m162_isdigitstring(a) && m162_isdigitstring(b)))
    return null;

  var span = Math.min(a.length, b.length);
  var r = "";

  for(var i = 0; i < span; i++) {
    var c1 = parseInt(a.charAt(i));
    var c2 = parseInt(b.charAt(i));
    if(c1 < c2)
      c1 += 10;
    r += (c1 - c2);
  }

  return r;
}

function m162_chainsum(s, n) {
  if(!m162_isdigitstring(s) || isNaN(n))
    return null;
  if(n == 0)
    return "";
  if(n <= s.length)
    return s.substring(0, n);
  if(s.length < 2)
    return null;

  for(var i = 0; s.length < n; i++) {
    var c = "" + (parseInt(s.charAt(i)) + parseInt(s.charAt(i+1)));
    s += c.charAt(c.length - 1);
  }

  return s;
}

function m162_permute_sortby(a, b) {
  if(a[0] < b[0])
    return -1;
  if(a[0] > b[0])
    return 1;
  if(a[1] < b[1])
    return -1;
  if(a[1] > b[1])
    return 1;
  return 0;
}

function m162_permute(s, k) {
  if(typeof s != "string" || typeof k != "string")
    return null;
  if(s.length < 1 || s.length != k.length)
    return null;

  var a = new Array(k.length);
  var b = new Array(k.length);
  var r = "";

  for(var i = 0; i < k.length; i++) { a[i] = [ k.charAt(i), i ]; }

  a.sort(m162_permute_sortby);

  for(var i = 0; i < a.length; i++) { b[a[i][1]] = s.charAt(i); }
  for(var i = 0; i < b.length; i++) { r += b[i]; }

  return r;
}

function M162AlphabetSubstitutor(orig, dest) {
  var len = Math.min(orig.length, dest.length);
  var so = orig.substring(0, len);
  var sd = dest.substring(0, len);

  this.e = new Object();
  this.d = new Object();

  for(var i = 0; i < len; i++) {
    this.e[so.charAt(i)] = sd.charAt(i);
    this.d[sd.charAt(i)] = so.charAt(i);
  }

  this.encode = function(s) {
    var r = "";

    for(var i = 0; i < s.length; i++) {
      var c = this.e[s.charAt(i)];
      if(c)
        r += c;
    }

    return r;
  }

  this.decode = function(s) {
    var r = "";

    for(var i = 0; i < s.length; i++) {
      var c = this.d[s.charAt(i)];
      if(c)
        r += c;
    }

    return r;
  }
}

function M162StraddlingCheckerboard(k, a1, a2) {
  var rowkeys = new Array();
  var rows = new Array;
  var e = new Object();
  var d = new Object();

  for(var i = 0; i < k.length; i++) {
    var c = a1.charAt(i);
    var kc = k.charAt(i);

    if(c == " ") {
      rowkeys[rowkeys.length] = kc;
      d[kc] = new Object();
    }
    else {
      e[c] = kc;
      d[kc] = c;
    }
  }

  for(var i = 0; i < rowkeys.length; i++) {
    var kc = rowkeys[i];
    var row = a2.substring(k.length * i, k.length * (i + 1));

    rows[rows.length] = row;

    for(var j = 0; j < k.length; j++) {
      var c = row.charAt(j);
      var kkc = k.charAt(j);
      e[c] = kc + kkc;
      d[kc][kkc] = c;
    }
  }

  this.k = k;
  this.a1 = a1;
  this.e = e;
  this.d = d;
  this.rowkeys = rowkeys;
  this.rows = rows;

  this.to_s = function() {
    var s = "    ";
    for(var i = 0; i < this.k.length; i++) { s += (this.k.charAt(i) + " "); }
    s += "\n  +-";
    for(var i = 0; i < this.k.length; i++) { s += "--"; }
    s += "\n  | ";
    for(var i = 0; i < this.a1.length; i++) { s += (this.a1.charAt(i) + " "); }

    for(var i = 0; i < this.rows.length; i++) {
      s += ("\n" + this.rowkeys[i] + " | ");
      for(j = 0; j < this.k.length; j++) {
        s += (this.rows[i].charAt(j) + " ");
      }
    }

    return s;
  }

  this.encode = function(s) {
    var r = "";

    for(var i = 0; i < s.length; i++) {
      var ec = this.e[s.charAt(i)];
      if(ec)
        r += ec;
    }

    return r;
  }

  this.decode = function(s) {
    var r = "";

    for(var i = 0; i < s.length; i++) {
      var dc = this.d[s.charAt(i)];
      if(dc) {
        if(typeof dc == "string")
          r += dc;
        else if(i+1 < s.length) {
          dc = dc[s.charAt(i+1)];
          if(dc) {
            r += dc;
            i++;
          }
        }
      }
    }

    return r;
  }

}

function M162ColumnarTransposer(columns, size) {
  var height = parseInt((size + columns - 1) / columns);
  this.width = columns;
  this.height = height;
  this.a = new Array(height);

  for(var i = 0; i < height - 1; i++) {
    this.a[i] = new Array(columns);
  }
  this.a[i] = new Array(columns - height*columns + size);

  this.clear = function(filler) {
    for(var i = 0; i < this.height; i++) {
      for(var j = 0; j < this.a[i].length; j++) {
        this.a[i][j] = filler;
      }
    }
  }

  this.to_s = function() {
    var r = "";

    for(var i = 0; i < this.height; i++) {
      for(var j = 0; j < this.a[i].length; j++) {
        r += this.a[i][j];
      }
      if(i + 1 < this.height)
        r += "\n";
    }

    return r;
  }

  this.fillhz = function(s) {
    var pos = 0;
    var r = "";

    for(var i = 0; i < this.height; i++) {
      for(var j = 0; j < this.a[i].length; j++) {
        this.a[i][j] = s.charAt(pos);
        pos++;
      }
    }
  }

  this.fillvt = function(k, s) {
    var b = new Array(k.length);
    var pos = 0;

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    for(var i = 0; i < this.width; i++) {
      var col = b[i][1];

      for(var j = 0; j < this.height; j++) {
        if(col < this.a[j].length) {
          this.a[j][col] = s.charAt(pos);
          pos++;
        }
      }
    }
  }

  this.fillhz_disrupted1 = function(k, s) {
    var b = new Array(k.length);
    var pos = 0;

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    var rowlen = this.width + 1;
    var tristart = 0;

    for(var i = 0; i < this.height; i++) {
      if(rowlen > this.a[i].length) {
        rowlen = b[tristart][1];
        tristart++;
        if(rowlen > this.a[i].length)
          rowlen = this.a[i].length;
      }

      for(var j = 0; j < rowlen; j++) {
        this.a[i][j] = s.charAt(pos);
        pos++;
      }

      rowlen++;
    }

    return pos;
  }

  this.fillhz_disrupted2 = function(k, s) {
    var b = new Array(k.length);
    var pos = 0;

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    var rowlen = this.width + 1;
    var tristart = 0;

    for(var i = 0; i < this.height; i++) {
      if(rowlen > this.a[i].length) {
        rowlen = b[tristart][1];
        tristart++;
        if(rowlen > this.a[i].length)
          rowlen = this.a[i].length;
      }

      for(var j = rowlen; j < this.a[i].length; j++) {
        this.a[i][j] = s.charAt(pos);
        pos++;
      }

      rowlen++;
    }

    return pos;
  }

  this.readhz = function() {
    var r = "";

    for(var i = 0; i < this.height; i++) {
      for(var j = 0; j < this.a[i].length; j++) {
        r += this.a[i][j];
      }
    }

    return r;
  }

  this.readvt = function(k) {
    var b = new Array(k.length);
    var r = "";

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    for(var i = 0; i < this.width; i++) {
      var col = b[i][1];

      for(var j = 0; j < this.height; j++) {
        if(col < this.a[j].length)
          r += this.a[j][col];
      }
    }

    return r;
  }

  this.readhz_disrupted1 = function(k) {
    var b = new Array(k.length);
    var r = "";

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    var rowlen = this.width + 1;
    var tristart = 0;

    for(var i = 0; i < this.height; i++) {
      if(rowlen > this.a[i].length) {
        rowlen = b[tristart][1];
        tristart++;
        if(rowlen > this.a[i].length)
          rowlen = this.a[i].length;
      }

      for(var j = 0; j < rowlen; j++) {
        r += this.a[i][j];
      }

      rowlen++;
    }

    return r;
  }

  this.readhz_disrupted2 = function(k) {
    var b = new Array(k.length);
    var r = "";

    for(var i = 0; i < k.length; i++) { b[i] = [ k.charAt(i), i ]; }
    b.sort(m162_permute_sortby);

    var rowlen = this.width + 1;
    var tristart = 0;

    for(var i = 0; i < this.height; i++) {
      if(rowlen > this.a[i].length) {
        rowlen = b[tristart][1];
        tristart++;
        if(rowlen > this.a[i].length)
          rowlen = this.a[i].length;
      }

      for(var j = rowlen; j < this.a[i].length; j++) {
        r += this.a[i][j];
      }

      rowlen++;
    }

    return r;
  }
}

// End of library, HTML display follows

function mgb162_get_elements() {
  if(!document.getElementById || !mgb162_get_elements.arguments)
    return false;

  var r = new Array(mgb162_get_elements.arguments.length);

  for(var i = 0; i < r.length; i++) {
    var c = document.getElementById(mgb162_get_elements.arguments[i])
    if(c)
      r[i] = c;
    else
      return false;
  }

  return r;
}

function mgb162_update_ncsum() {
  var c = mgb162_get_elements("m162_ncsum1", "m162_ncsum2", "m162_ncsum3");
  if(c)
    c[2].value = m162_ncsum(c[0].value, c[1].value);
}

function mgb162_update_ncsub() {
  var c = mgb162_get_elements("m162_ncsub1", "m162_ncsub2", "m162_ncsub3");
  if(c)
    c[2].value = m162_ncsub(c[0].value, c[1].value);
}

function mgb162_update_chainsum() {
  var c = mgb162_get_elements("m162_chainsum1", "m162_chainsum2");
  if(c)
    c[1].value = m162_chainsum(c[0].value, 50) + "...";
}

function mgb162_update_permut() {
  var c = mgb162_get_elements("m162_permut1", "m162_permut2", "m162_permut3");
  if(!c)
    return;

  var k = c[0].value.toUpperCase();
  var t = c[1].value.toUpperCase();
  c[0].value = k;
  c[1].value = t;
  c[2].value = m162_permute(t, k);
}

function mgb162_update_alfa(reverse) {
  var c = mgb162_get_elements("m162_alfa1", "m162_alfa2", "m162_alfa3",
    "m162_alfa4");
  if(!c) return;

  var a1 = c[0].value.replace(/\s+/g, "").toUpperCase();
  c[0].value = a1;
  var a2 = c[1].value.replace(/\s+/g, "").toUpperCase();
  c[1].value = a2;

  if(reverse) {
    c[2].value = "";

    if(a1.length > 0 && a1.length == a2.length) {
      var t = c[3].value.toUpperCase();
      c[3].value = t;
      t = t.replace(/\s+/g, "");
      var as = new M162AlphabetSubstitutor(a1, a2);
      c[2].value = as.decode(t);
    }
  }
  else {
    c[3].value = "";

    if(a1.length > 0 && a1.length == a2.length) {
      var t = c[2].value.toUpperCase();
      c[2].value = t;
      t = t.replace(/\s+/g, "");
      var as = new M162AlphabetSubstitutor(a1, a2);
      c[3].value = as.encode(t);
    }
  }
}

function mgb162_transp_to_s(p, k) {
  var r = k + "\n";

  for(var i = 0; i < k.length; i++) { r += "-"; }
  r += "\n" + p.to_s();

  return r;
}

function mgb162_update_transp(reverse) {
  var c = mgb162_get_elements("m162_transp1", "m162_transp2", "m162_transp3",
    "m162_transp4");
  if(!c) return;

  var k = c[0].value.replace(/\s+/g, "").toUpperCase();
  c[0].value = k;

  c[2].value = "";

  if(k.length > 0) {
    var ct;

    if(reverse) {
      var s = c[3].value.replace(/\s+/g, "").toUpperCase();

      if(s.length > 0) {
        ct = new M162ColumnarTransposer(k.length, s.length);
        ct.fillvt(k, s);
        c[2].value = mgb162_transp_to_s(ct, k);
        c[1].value = ct.readhz();
      }
    }
    else {
      var s = c[1].value.toUpperCase();
      c[1].value = s;
      s = s.replace(/\s+/g, "");

      if(s.length > 0) {
        ct = new M162ColumnarTransposer(k.length, s.length);
        ct.fillhz(s);
        c[2].value = mgb162_transp_to_s(ct, k);
        c[3].value = ct.readvt(k);
      }
    }
  }
}

function mgb162_update_sc(reverse) {
  var c = mgb162_get_elements("m162_sc1", "m162_sc2", "m162_sc3",
    "m162_sc4", "m162_sc5", "m162_sc6");
  if(!c) return;

  var k = c[0].value.replace(/\s+/g, "").toUpperCase();
  c[0].value = k;
  c[1].value = "";
  c[3].value = "";

  if(k.length == 10) {
    var kp = m162_permute("123456789A", k).replace("A", "0");
    c[1].value = kp;

    var a1, a2;

    if(c[5].value == "en") {
      a1 = "AT ONE SIR";
      a2 = "BCDFGHJKLMPQUVWXYZ.*";
    }
    else if(c[5].value == "ru") {
      a1 = "СНЕГОПА   ";
      a2 = "БЖ.К#РФЧЫЮВЗ,Л^ТХШБЯДИ?М>УЦЩЭ=";
    }
    else {
      a1 = "IR DE ASNO";
      a2 = "BCFGHJKLMPQTUVWXYZ.*";
    }
    var sc = new M162StraddlingCheckerboard(kp, a1, a2);
    c[3].value = sc.to_s();

    if(reverse) {
      var ct = c[4].value.replace(/\s+/g, "");
      if(ct.length > 0) {
        c[2].value = sc.decode(ct);
      }
    }
    else {
      var t = c[2].value;
      if(t.length > 0) {
        t = t.toUpperCase();
        c[2].value = t;
        t = t.replace(/\s+/g, "")
        c[4].value = sc.encode(t);
      }
    }
  }
}

function mgb162_update_trd(reverse) {
  var c = mgb162_get_elements("m162_trd1", "m162_trd2", "m162_trd3",
    "m162_trd4", "m162_trd5");
  if(!c) return;

  var k = c[0].value.replace(/\s+/g, "").toUpperCase();
  c[0].value = k;

  c[2].value = "";

  if(k.length > 0) {
    var ct;

    if(reverse) {
      var s = c[4].value.replace(/\s+/g, "").toUpperCase();

      if(s.length > 0) {
        ct = new M162ColumnarTransposer(k.length, s.length);
        ct.fillvt(k, s);
        c[3].value = mgb162_transp_to_s(ct, k);
        var t1 = ct.readhz_disrupted1(k);
        c[1].value = t1 + ct.readhz_disrupted2(k);
        ct.clear(" ");
        ct.fillhz_disrupted1(k, t1);
        c[2].value = mgb162_transp_to_s(ct, k);
      }
    }
    else {
      var s = c[1].value.toUpperCase();
      c[1].value = s;
      s = s.replace(/\s+/g, "");

      if(s.length > 0) {
        ct = new M162ColumnarTransposer(k.length, s.length);
        ct.clear(" ");
        var n = ct.fillhz_disrupted1(k, s);
        c[2].value = mgb162_transp_to_s(ct, k);
        ct.fillhz_disrupted2(k, s.substring(n));
        c[3].value = mgb162_transp_to_s(ct, k);
        c[4].value = ct.readvt(k);
      }
    }
  }
}
