//    Hikij
//    wiki.js
//    Copyright 2006 Matthew Sackman
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

var homePage = 'HikijHome'; // set this to the WikiPage you want loaded as the homepage of the wiki
var serverPath = '/Wiki.hs'; // set this to the path needed to reach your server side script

window.onload = fetchHomePage;

function fetchHomePage() {
  $('sidebar').innerHTML = '';
  addToHistory(makeWikiLink('RecentChanges'), $('sidebar'));
  fetchPage(homePage);
}

function fetchPage(pageName) {
  if (! isWikiWord(pageName)) {
    alert('Not WikiWord: '+pageName);
    return false;
  }
  var jsonObject = new Object();
  jsonObject.pageName = pageName;
  var myAjax = new Ajax.Request
    (serverPath,
     {  method: 'post',
        postBody: $H({method: 'fetch',
                      json: jsonObject.toJSONString()}
                    ).toQueryString(),
        onSuccess : successFn(pageName, ' last updated at ')
     }
    );
  return true;
}

function fetchPageVersion(pageName, versionId) {
  if (! isWikiWord(pageName)) {
    alert('Not WikiWord: '+pageName);
    return false;
  }
  var jsonObject = new Object();
  jsonObject.pageName = pageName;
  jsonObject.version = versionId;
  var myAjax = new Ajax.Request
    (serverPath,
     {  method: 'post',
        postBody: $H({method: 'fetch',
                      json: jsonObject.toJSONString()}
                    ).toQueryString(),
        onSuccess : successFn(pageName, ' saved at ')
     }
    );
  return true;
}

function successFn(pageName, joiningText) {
  var sideBarEl = $('sidebar');
  var mainEl = $('main');
  if ("RecentChanges" == pageName) {
    return function(response) {
      var obj = response.responseText.parseJSON();
      var text = '<h1>RecentChanges</h1>';
      var markup = '';
      var date = '';
      var eachFn = function(elem, _idx, _ary) {
        if (elem.date != date) {
          date = elem.date;
          markup += '\n\n* ' + date;
        }
        markup += '\n    * ' + elem.time + ': ' + elem.pageName;
      };
      obj.changes.forEach(eachFn);
      text += markdownToHTML(markup, obj.pages);
      mainEl.innerHTML = text;
      mainEl.className = 'mainRead';
      mainEl.ondblclick = function(_event) {};
      addToHistory(makeWikiLink(pageName), sideBarEl);
      $('instrReading').style.visibility = 'hidden';
      $('instrEditing').style.visibility = 'hidden';
      $('versionsBox').style.visibility = 'hidden';
    }
  } else {
    return function(response) {
      var obj = response.responseText.parseJSON();
      var textOrig = obj.text;
      var date = obj.date;
      var pages = obj.pages;
      var textNotUndef = textOrig ? textOrig : '';
      var editFun = edit(mainEl, textNotUndef, pageName, date, pages);
      mainEl.innerHTML = '<h1>' + pageName + '</h1>\n' + markdownToHTML(textNotUndef, pages);
      var metaDiv = document.createElement('div');
      metaDiv.innerHTML = pageName + joiningText + date + '. ';
      var versionsSpan = document.createElement('span');
      versionsSpan.onclick = showAllVersions(pageName, date);
      versionsSpan.innerHTML = 'Edit History';
      versionsSpan.style.textDecoration = 'underline';
      metaDiv.appendChild(versionsSpan);
      metaDiv.className = 'articleMeta';
      mainEl.appendChild(metaDiv);
      mainEl.ondblclick = editFun;
      mainEl.className = 'mainRead';
      addToHistory(makeWikiLink(pageName), sideBarEl);
      $('instrReading').style.visibility = 'visible';
      $('instrEditing').style.visibility = 'hidden';
      $('versionsBox').style.visibility = 'hidden';
      if (! textOrig) {
        editFun(null);
      }
    }
  }
}

function edit(mainEl, text, pageName, date, pages) {
  return function(_event) {
    $('instrReading').style.visibility = 'hidden';
    $('instrEditing').style.visibility = 'visible';
    $('versionsBox').style.visibility = 'hidden';
    mainEl.className = 'mainEdit';

    mainEl.innerHTML = '<h1 style="position: fixed;">' + pageName + '</h1>\n';

    var formEl = document.createElement('form');
    var textAreaEl = document.createElement('textarea');
    textAreaEl.value = text;
    textAreaEl.className = 'editBox';
    textAreaEl.rows = 20;
    formEl.appendChild(textAreaEl);
    mainEl.appendChild(formEl);

    var previewEl = document.createElement('div');
    previewEl.className = 'previewBox';
    mainEl.appendChild(previewEl);
    previewEl.innerHTML = markdownToHTML(text, pages);
    var saveFun = editDone(textAreaEl, mainEl, pageName);
    textAreaEl.onkeyup = function(event){
                            var newText = textAreaEl.value;
                            previewEl.innerHTML = markdownToHTML(newText, pages);
                            if (event.ctrlKey && event.keyCode == 13) { // 13 == return/enter
                              saveFun(event);
                            }
                            return true;
                          };
    mainEl.ondblclick = saveFun;
  }
}

function editDone(textAreaEl, mainEl, pageName) {
  return function(event) {
    if (! event.ctrlKey) {
      return;
    }
    var text = textAreaEl.value;
    if (! text) {
      return;
    }
    var jsonObject = new Object();
    jsonObject.pageName = pageName;
    jsonObject.text = text;
    var myAjax = new Ajax.Request
      (serverPath,
       {  method: 'post',
          postBody: $H({method: 'save',
                        json: jsonObject.toJSONString()}
                      ).toQueryString(),
          onSuccess : successFn(pageName, ' last updated at ')
       }
      );
    return true;
  }
}

function isWikiWord(name) {
  if (null == name || 0 == name.length) {
    return false;
  }
  var start = name.charAt(0);
  if (start != start.toUpperCase()) {
    return false;
  }
  if (null == name.match(/[a-z][A-Z]/)) {
    return false;
  }
  if (null != name.match(/[^a-zA-Z0-9]/)) {
    return false;
  }
  return true;
}

function makeWikiLink(name) {
  if (isWikiWord(name)) {
    var link = document.createElement('a');
    link.href = name;
    link.className = 'wikiLink';
    link.onclick = function(event) {fetchPage(name); return false;};
    link.title = name;
    link.textContent = name;
    return link;
  } else {
    return document.createTextNode(name);
  }
}

function makeWikiLinkString(name, pages) {
  if (isWikiWord(name)) {
    var known = pages.indexOf(name) != -1;
    var linkClass = known ? 'wikiLink' : 'wikiLinkUnknown';
    var l = '<a href="' + name + '" class="' + linkClass + '" title="'
           + name + '" onclick="fetchPage(\'' + name + '\'); return false;">'
           + name + '</a>';
    return l;
  } else {
    return name;
  }
}

function addToHistory(newElem, sideBarEl) {
  var itemOne = sideBarEl.firstChild;
  if (null == itemOne || itemOne.tagName.toUpperCase() != 'A') {
    sideBarEl.appendChild(newElem);
  } else {
    if (itemOne.href != newElem.href ||
        itemOne.title != newElem.title ||
        itemOne.textContent != newElem.textContent) {
      sideBarEl.insertBefore(newElem, itemOne);
      sideBarEl.insertBefore(document.createElement('br'), itemOne);
    }
  }
}

function showAllVersions(pageName, currentDate) {
  return function(_event) {
    var jsonObject = new Object();
    jsonObject.pageName = pageName;
    var myAjax = new Ajax.Request
      (serverPath,
       {  method: 'post',
          postBody: $H({method: 'listVersions',
                        json: jsonObject.toJSONString()}
                      ).toQueryString(),
          onSuccess : displayAllVersions(pageName, currentDate)
     }
    );
    return true;
  }
}

function displayAllVersions(pageName, currentDate) {
  var versionsBox = $('versionsBox');
  return function(response) {
    var obj = response.responseText.parseJSON();
    var versions = obj.versions;
    if (! versions) {
      return;
    }
    versionsBox.innerHTML = '';
    var olEl = document.createElement('ol');
    versionsBox.appendChild(olEl);
    versions.forEach(function(elem, _idx, _ary) {
                       var liEl = document.createElement('li');
                       liEl.onclick = loadVersion(pageName, elem.id);
                       liEl.innerHTML = elem.date;
                       if (elem.date == currentDate) {
                         liEl.className = 'currentVersion';
                       }
                       olEl.appendChild(liEl);
                     }
                    );
    var closeDiv = document.createElement('span');
    closeDiv.innerHTML = 'Close';
    closeDiv.className = 'articleMeta';
    versionsBox.appendChild(closeDiv);

    versionsBox.style.visibility = 'visible';
    versionsBox.onclick = function(_event) {
                            versionsBox.style.visibility = 'hidden';
                            return true;
                          };
  }
}

function loadVersion(pageName, versionId) {
  return function(_event) {
    return fetchPageVersion(pageName, versionId);
  }
}
