var addEvent = (function () {
  var setListener;
  return function (el, ev, fn) {
    if (!setListener) {
      if (el.addEventListener) {
        setListener = function (el, ev, fn) {
          el.addEventListener(ev, fn, false);
        };
      } else if (el.attachEvent) {
        setListener = function (el, ev, fn) {
          el.attachEvent('on' + ev, fn);
        };
      } else {
        setListener = function (el, ev, fn) {
          el['on' + ev] = fn;
        };
      }
    }
    setListener(el, ev, fn);
  };
}());
if (!Date.now) {
  Date.now = function now() {
    return new Date().getTime();
  };
}
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (searchElement, fromIndex) {
    var k;
    if (this == null) {
      throw new TypeError('"this" is null or not defined');
    }
    var O = Object(this);
    var len = O.length >>> 0;
    if (len === 0) {
      return -1;
    }
    var n = +fromIndex || 0;
    if (Math.abs(n) === Infinity) {
      n = 0;
    }
    if (n >= len) {
      return -1;
    }
    k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
    while (k < len) {
      var kValue;
      if (k in O && O[k] === searchElement) {
        return k;
      }
      k++;
    }
    return -1;
  };
}

var simplePoll = (function () {
  var container = document.getElementById('container');
  container.style.visibility = 'hidden';
  // default configuration - stuff that can be changed via SC Attachments / Parameters
  var cfg = {
    max_load_tries: 60,
    id: null,
    data_file: null,
    css_file: null,
    css: null,
    save_mode: null,
    question: null,
    options_count: null,
    options: []
  };
  var selected_option = null;
  var vote_group = null;
  var empty_count = [];

  var setCfg = function () {
    cfg.id = VLE.get_param('_a');
    var sm = VLE.get_param('save_mode') || false;
    //cfg.save_mode = cfg.save_mode.toLowerCase()==='true'?true:(cfg.save_mode.toLowerCase()==='false'?false:cfg.save_mode);
    console.log('sm: ' + sm);
    console.log(typeof sm);
    try {
      cfg.save_mode = JSON.parse(sm);
      console.log(typeof cfg.save_mode);

    } catch (e) {
      cfg.save_mode = sm;
    }
    cfg.question = VLE.get_param('question') || 'Choose an option.';
    cfg.options_count = VLE.get_param('options_count');
    if (cfg.options_count !== null) {
      var i, opt;
      for (i = 0; i < cfg.options_count; i++) {
        opt = VLE.get_param('option' + i) || '[undefined option]';
        if (opt) {
          cfg.options.push(opt);
        }
        empty_count.push(0);
      }
    }
    // initialise
    init();
  };

  var init = function () {
    if (container.firstChild) {
      container.removeChild(container.firstChild);
    } // clean container
    var div, para, span, i, list, id, opt, item, rb, label, box, bar, pc, btn, bcr;
    if (cfg.options_count !== null) {
      div = document.createElement('div');
      div.setAttribute('id', 'question');
      para = document.createElement('p');
      para.setAttribute('class', 'q');
      processTokens(para, tokeniseContent(cfg.question));
      div.appendChild(para);
      list = document.createElement('ul');
      for (i = 0; i < cfg.options_count; i++) {
        id = 'rb' + i;
        opt = cfg.options[i];
        item = document.createElement('li');
        rb = document.createElement('input');
        rb.setAttribute('id', id);
        rb.setAttribute('type', 'radio');
        rb.setAttribute('name', 'poll');
        label = document.createElement('label');
        label.setAttribute('for', id);
        processTokens(label, tokeniseContent(opt));
        box = document.createElement('span');
        box.setAttribute('class', 'box');
        bar = document.createElement('span');
        bar.setAttribute('id', id + '_bar');
        bar.setAttribute('class', 'bar');
        pc = document.createElement('span');
        pc.setAttribute('id', id + '_pc');
        pc.setAttribute('class', 'pc');
        pc.appendChild(document.createTextNode(''));
        box.appendChild(bar);
        item.appendChild(rb);
        item.appendChild(label);
        item.appendChild(box);
        item.appendChild(pc);
        list.appendChild(item);
      }
      div.appendChild(list);
      para = document.createElement('p');
      para.setAttribute('id', 'fb');
      btn = document.createElement('button');
      btn.appendChild(document.createTextNode('Submit vote'));
      para.appendChild(btn);
      addEvent(btn, 'click', doVote);
      span = document.createElement('span');
      span.setAttribute('id', 'fb_msg');
      para.appendChild(span);
      div.appendChild(para);
      container.appendChild(div);
      bcr = para.getBoundingClientRect();
      para.style.height = ((bcr.bottom - bcr.top) | 1) + 'px';

      // Show the group controls if using a group mode - regional or tutor groups.
      // if (true) {
      if (cfg.save_mode !== false && cfg.save_mode !== true) {
        var grp_ctrls = document.createElement('div');
        grp_ctrls.id = 'grp_ctrls';
        var chooser = VLE.make_group_chooser(cfg.save_mode, changeGroup, true, function (msg) {
          alert('There was an error: ' + msg);
        });
        grp_ctrls.appendChild(chooser);
        var view_btn = document.createElement('button');
        view_btn.appendChild(document.createTextNode('View current results'));
        grp_ctrls.appendChild(view_btn);
        addEvent(view_btn, 'click', viewVotes);

        var zap_btn = document.createElement('button');
        zap_btn.appendChild(document.createTextNode('Zap'));
        grp_ctrls.appendChild(zap_btn);
        addEvent(zap_btn, 'click', zap);

        container.appendChild(grp_ctrls);
      } else {
        getUserVote();
      }
    } else {
      para = document.createElement('p');
      para.appendChild(document.createTextNode('No options defined for this poll.'));
      container.appendChild(para);
      container.style.visibility = 'visible';
    }

    var resize = setInterval(function () {
      if (window.frameElement) {
        bcr = container.getBoundingClientRect();
        var h = (bcr.bottom - bcr.top) | 1;
        console.log('Setting frameElement height to ' + h + 'px');
        window.frameElement.style.height = h + 'px';
      }
    }, 1000);

    container.style.visibility = 'visible';
  };

  var zap = function () {
    VLE.set_server_data(true, {
      opt: '',
      grp: ''
    }, function () {}, function () {});
    VLE.set_server_data(cfg.save_mode, {
      count: ''
    }, function () {}, function () {});
  };

  var doVote = function () {
    var i, rb;
    for (i = 0; i < cfg.options_count; i++) {
      if (document.getElementById('rb' + i).checked) {
        selected_option = i;
      }
    }
    if (selected_option !== null) {
      VLE.set_server_data(true, {
          opt: selected_option,
          grp: (typeof cfg.save_mode == 'string' ? cfg.save_mode : '')
        },
        function () {
          console.log('doVote :: Vote registered, about to update count...');
          VLE.get_server_data(cfg.save_mode, ['count'],
            function (vals) {
              console.log('doVote :: Reading group - in OK...');
              var cur_count = vals.count === '' ? '' : JSON.parse(vals.count);
              var new_count = cur_count.slice() || empty_count.slice();
              new_count[selected_option]++;
              var data_obj = {
                count: JSON.stringify(new_count),
                dummy: ''
              };
              var expected = {
                count: cur_count === '' ? '' : JSON.stringify(cur_count),
                dummy: ''
              };
              console.log('doVote :: About to write group data... JSON.stringify(data_obj) = ' + JSON.stringify(data_obj) + '.');
              VLE.set_server_data(cfg.save_mode, data_obj, viewVotes, viewVotes, expected, saveCountRetry);
            },
            function () {
              viewVotes();
            }
          );
        },
        function () {
          viewVotes();
        }
      );
    }
  };

  var setPollEnabled = function (state) {
    for (i = 0; i < cfg.options_count; i++) {
      if (state === true) {
        document.getElementById('rb' + i).removeAttribute('disabled');
        document.getElementById('rb' + i).removeAttribute('checked');
        document.getElementById('fb').removeAttribute('class');
        document.getElementById('rb' + i + '_bar').setAttribute('style', 'width:0%;');
        document.getElementById('rb' + i + '_pc').firstChild.nodeValue = '';
      } else {
        document.getElementById('rb' + i).setAttribute('disabled', 'disabled');
        document.getElementById('fb').setAttribute('class', 'has_voted');
      }
    }
  };
  
  var viewVotes = function () {
    setPollEnabled(false);
    var fb_msg = document.getElementById('fb_msg');
    while (fb_msg.firstChild) {
      fb_msg.removeChild(fb_msg.firstChild);
    }
    VLE.get_server_data(cfg.save_mode, ['count'],
      function (vals) {
        var i, poll_data, pc, max, txt;
        poll_data = vals.count === '' ? null : JSON.parse(vals.count);
        max = 0;
        if (poll_data !== null) {
          for (i = 0; i < cfg.options_count; i++) {
            max += poll_data[i] || 0;
          }
          for (i = 0; i < cfg.options_count; i++) {
            pc = poll_data[i] / max * 100;
            document.getElementById('rb' + i + '_bar').setAttribute('style', 'width:' + pc + '%;');
            document.getElementById('rb' + i + '_pc').firstChild.nodeValue = pc.toFixed(0) + '%';
          }
        } else {
          for (i = 0; i < cfg.options_count; i++) {
            document.getElementById('rb' + i + '_bar').setAttribute('style', 'width:0%;');
            document.getElementById('rb' + i + '_pc').firstChild.nodeValue = '0%';
          }
        }

        if (selected_option === null) {
          txt = 'You have not voted.';
        } else {
          txt = 'You have voted';
          txt += (typeof cfg.save_mode == 'string' ? (' in ' + (cfg.save_mode == vote_group ? 'this' : 'another') + ' group') : '') + '.';
        }

        fb_msg.appendChild(document.createTextNode(txt));
        fb_msg.appendChild(document.createElement('br'));
        fb_msg.appendChild(document.createTextNode('Total number of votes: ' + max));
      },
      function () { // random
        var i, poll_data, pc, max;
        max = selected_option ? 99 : 100;
        fb_msg.appendChild(document.createTextNode('Cannot save/read data. Try again later.'));
        fb_msg.appendChild(document.createElement('br'));
        fb_msg.appendChild(document.createTextNode('Total number of participants so far is ' + (100) + '. This data is simulated.'));
        for (i = 0; i < cfg.options_count; i++) {
          if (i == cfg.options_count - 1) {
            pc = max;
          } else {
            pc = ~~(Math.random() * max);
            max -= pc
          }
          if (i == selected_option) {
            pc++;
            max++;
          }
          document.getElementById('rb' + i + '_bar').setAttribute('style', 'width:' + pc + '%;');
          document.getElementById('rb' + i + '_pc').firstChild.nodeValue = pc + '%';
        }
      }
    );
  };

  var changeGroup = function (grp) {
    if (grp !== null) {
      cfg.save_mode = 'g' + grp.id;
    }
    getUserVote();
  };

  var getUserVote = function () {
    setPollEnabled(false);
    var fb_msg = document.getElementById('fb_msg');
    while (fb_msg.firstChild) {
      fb_msg.removeChild(fb_msg.firstChild);
    }
    fb_msg.appendChild(document.createTextNode('Loading data...'));
    VLE.get_server_data(
      true, ['opt', 'grp'],
      function (vals) {
        selected_option = vals.opt || null;
        vote_group = vals.grp || null;
        if (selected_option && (typeof cfg.save_mode == 'boolean' || cfg.save_mode == vote_group)) {
          document.getElementById('rb' + selected_option).removeAttribute('disabled');
          document.getElementById('rb' + selected_option).setAttribute('checked', 'checked');
          document.getElementById('rb' + selected_option).setAttribute('disabled', 'disabled');
        }
        if (selected_option) {
          document.getElementById('rb' + selected_option).removeAttribute('disabled');
          document.getElementById('rb' + selected_option).removeAttribute('checked');
          document.getElementById('rb' + selected_option).setAttribute('disabled', 'disabled');
          viewVotes();
        } else {
          setPollEnabled(true);
        }
      },
      function () {
        selected_option = null;
        vote_group = null;
        setPollEnabled(true);
      }
    );
  };

  var saveCountRetry = function (actual) {
    console.log('saveCountRetry :: ...');
    var cur_count = actual ? (actual.count === '' ? '' : JSON.parse(actual.count)) : '';
    var new_count = cur_count.slice() || empty_count.slice();
    new_count[selected_option]++;
    var data_obj = {
      count: JSON.stringify(new_count),
      dummy: ''
    };
    var expected = {
      count: cur_count === '' ? '' : JSON.stringify(cur_count),
      dummy: ''
    };
    VLE.set_server_data(cfg.save_mode, data_obj, viewVotes, viewVotes, expected, saveCountRetry);
  };

  var tokeniseContent = function (content) {
    var tokens = [];
    var idx_s = 0;
    var idx_e = content.length;
    var tok_rx = /<\/*[a-z].*?>/g;
    var tok_res;
    while (tok_res = tok_rx.exec(content)) {
      if (idx_s < tok_res.index) {
        tokens.push(content.substring(idx_s, tok_res.index));
      }
      tokens.push(tok_res[0]);
      idx_s = tok_rx.lastIndex;
    }
    if (idx_s < idx_e) {
      tokens.push(content.substring(idx_s, idx_e));
    }
    return tokens;
  };

  var processTokens = function (cur_node, tokens) {
    var num_tokens = tokens.length;
    var ele_stack = [];
    for (var t = 0; t < num_tokens; t++) {
      var tok = tokens[t];
      if (tok.indexOf('</') == 0) { // end tag
        if (tok == '</layoutgrid>') {
          var ele = document.createElement('div');
          ele.setAttribute('class', 'clr');
          cur_node.appendChild(ele);
        }
        var base = ele_stack.pop();
        base.appendChild(cur_node);
        cur_node = base;
      } else if (tok.indexOf('<') == 0) {
        // start tag
        var ele_rx = /<([a-z]+)(\s+.+=".*")*(\s*\/\s*)?>/
        var ele_res = ele_rx.exec(tok);
        var tag = ele_res[1];
        var ele = null;
        switch (tag) {
          case 'layoutgrid':
            {
              ele = document.createElement('div');ele.setAttribute('class', 'grid');
            }
            break;
          case 't':
            {
              ele = document.createElement('div');
            }
            break;
          case 'gap':
          case 'indent':
            {
              ele = document.createElement('div');ele.setAttribute('class', tag);
            }
            break;
          default:
            {
              ele = document.createElement(tag);
            }
        }
        if (ele_res[2] && !(tag == 'layoutgrid')) { // attributes
          var att_rx = /(\S+?)="(.*?)"/g;
          var att_res;
          while (att_res = att_rx.exec(ele_res[2])) {
            ele.setAttribute(att_res[1], att_res[2]);
          }
        }
        if (ele_res[3]) { // short tag
          cur_node.appendChild(ele);
        } else {
          ele_stack.push(cur_node);
          cur_node = ele;
        }
      } else { // text
        cur_node.appendChild(document.createTextNode(parseHtmlEnteties(tok)));
      }
    }
  };

  var parseHtmlEnteties = function (text_in) {
    return text_in.replace(/&#([0-9]{1,3});/gi, function (match, numStr) {
      var num = parseInt(numStr, 10);
      return String.fromCharCode(num);
    }).replace(/&#x([a-fA-F0-9]{1,4});/gi, function (match, numStr) {
      var num = parseInt(numStr, 16);
      return String.fromCharCode(num);
    });
  };

  var outputDate = function (ms, want_time) {
    return_val = '';
    ms = parseInt(ms);
    if (!isNaN(ms)) {
      var months = ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
      var d = new Date(ms);
      var time_str = '';
      if (want_time !== false) {
        var h = d.getHours();
        var m = d.getMinutes();
        //var s = d.getUTCSeconds();
        time_str += ' at ' + (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m; //+':'+(s<10?'0':'')+s;
      }
      return_val = d.getFullYear() + '-' + months[d.getMonth()].substr(0, 3) + '-' + d.getDate() + time_str;
    }
    return return_val;
  };

  var load = function () {
    var load_try_ctr = 0;
    var loading = setInterval(function () {
      if (typeof VLE !== 'undefined') {
        container.style.visibility = 'hidden';
        clearInterval(loading);
        setCfg();
      } else if (load_try_ctr == cfg.max_load_tries) {
        clearInterval(loading);
        container.innerHTML = '<div class="msg"><p>Could not load this activity.</p></div>';
        container.style.visibility = 'visible';
      } else {
        container.innerHTML = '<div class="msg"><p>Loading...</p></div>';
        container.style.visibility = 'visible';
        load_try_ctr++;
      }
    }, 100);
  };
  
  return {
    load: load
  };
}());

simplePoll.load();