/**
 * Wikiwyg.PmWiki.js -- Client-side integration code for Wikiwyg in PmWiki
 * Copyright 2006 Evan Prodromou <evan@prodromou.name>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

window.onload = function() {

     var wikiwyg = new Wikiwyg.PmWiki();

     if (!pmwiki || !pmwiki.pagename) {
          return;
     }

     wikiwyg.pagename = pmwiki.pagename;

     var config = {
          javascriptLocation: pmwiki.pubpath + "/wikiwyg/lib/",
          doubleClickToEdit: true,
          modeClasses: ['Wikiwyg.Wysiwyg.PmWiki',
                        'Wikiwyg.Wikitext.PmWiki',
                        'Wikiwyg.Preview.PmWiki',
                        'Wikiwyg.HTML'],
          toolbar: {
                    imagesLocation: pmwiki.pubpath + "/wikiwyg/images/",
                    controlLayout:
                    [ 'save', 'cancel', 'mode_selector', '/',
                     // 'selector',
                     'h1', 'h2', 'h3', 'h4', 'p', 'pre', '|',
                     'bold', 'italic', 'underline', 'strike', '|',
                     'link', 'www', 'unlink', '|',
                     'ordered', 'unordered', 'hr', '|',
                     'indent', 'outdent', '|',
                     // 'table', '|',
                     'help'
                     ]
          },
          wikitext: {
               javascriptLocation: pmwiki.pubpath + "/wikiwyg/lib/",
               supportCamelCaseLinks: pmwiki.wikiwords,
               editHeightMinimum: 10,
               editHeightAdjustment: 1.3,
               textareaId: null,
               clearRegex: null,
          }
     };

     var editdiv = document.getElementById('wikiedit');

     if (editdiv) {
          initializeEditPage(wikiwyg, config, editdiv);
     } else {
          var mydiv = document.getElementById('wikitext');
          if (mydiv) {
               initializeBrowsePage(wikiwyg, config, mydiv);
          }
     }
}

function initializeBrowsePage(wikiwyg, config, mydiv) {
     
     wikiwyg.createWikiwygArea(mydiv, config);

     if (!wikiwyg.enabled) return;

     var parts = wikiwyg.pagename.split('.');
     var url = wikiwyg.make_page_url(parts[0], parts[1]) + '?action=edit';
     var esc = re_escape(url);
     var re = new RegExp('^' + esc + '$');
     Wikiwyg.changeLinksMatching('href', re,
        function() { wikiwyg.editMode(); return false }
     );
}

function initializeEditPage(wikiwyg, config, editdiv) {

     config.firstMode = 'Wikiwyg.Wikitext.PmWiki';
     
     var forms = editdiv.getElementsByTagName('form');
     if (!forms) {
          return;
     }
     var form = forms[0];
     var textareas = form.getElementsByTagName('textarea');
     if (!textareas) {
          return;
     }
     var textarea = textareas[0];
     var wikitext = textarea.textContent;
     
     var mydiv = document.getElementById('wikitext');
     mydiv.innerHTML = "";
     
     wikiwyg.createWikiwygArea(mydiv, config);
     
     if (!wikiwyg.enabled) return;

     wikiwyg.editMode();
     
     var wikitext_mode = wikiwyg.mode_objects['Wikiwyg.Wikitext.PmWiki'];
     
     wikitext_mode.setTextArea(wikitext);
}

function re_escape(str) {
     return str.replace(/[\^\$\\\?\*\.\[\]\(\)\+]/g, "\\$&");
}

var proto  = new Subclass('Wikiwyg.PmWiki', 'Wikiwyg');

proto.submit_action_form = function(action, value) {
    value['action'] = action;
    var form = document.createElement('form');
    form.setAttribute('action', pmwiki.scripturl);
    form.setAttribute('method', 'POST');
    for (var name in value) {
        var input = document.createElement('input');
        input.setAttribute('type', 'hidden');
        input.setAttribute('name', name);
        input.setAttribute('value', value[name])
        form.appendChild(input);
    }
    var div = this.div;
    div.parentNode.insertBefore(form, div);
    form.submit();
}

proto.saveChanges = function() {
    var self = this;
    var submit_changes = function(wikitext) {
        self.submit_action_form(
            'edit',
	    { 'post': '1',
	      'n': self.pagename,
	      'basetime': pmwiki.basetime,
	      'text': wikitext }
        );
    }
    if (Wikiwyg.Wikitext.prototype.isPrototypeOf(this.current_mode)) {
        submit_changes(this.current_mode.toWikitext());
    }
    else {
        this.current_mode.toHtml(
            function(html) {
                var wikitext_mode = self.mode_objects['Wikiwyg.Wikitext.PmWiki'];
                wikitext_mode.convertHtmlToWikitext(
                    html,
                    function(wikitext) { submit_changes(wikitext) }
                );
            }
        );
    }
};

proto.text_to_pagename = function(text) {
     var lparts = text.split(" ");
     var textpage = "";
     for (var i in lparts) {
          var lpart = lparts[i];
          var uclpart = lpart.substr(0, 1).toUpperCase() + lpart.substr(1);
          textpage = textpage + uclpart;
     }
     return textpage;
}

proto.get_current_group = function(text) {
     var parts = this.pagename.split('.');
     return parts[0];
}

proto.make_page_url = function(group, page) {
     if (pmwiki.pathinfo) {
		  return pmwiki.scripturl + '/' +
			   encodeURIComponent(group) + '/' +
			   encodeURIComponent(page);
	 } else {
		  return pmwiki.scripturl + '?n=' +
			   encodeURIComponent(group) + '.' +
			   encodeURIComponent(page);
	 }
}

proto = new Subclass('Wikiwyg.Wikitext.PmWiki', 'Wikiwyg.Wikitext');

proto.markupRules = {
     p: ['start_lines', ''],
	 pre: ['start_lines', ' '],
	 h1: ['start_line', '!'],
	 h2: ['start_line', '!!'],
	 h3: ['start_line', '!!!'],
	 h4: ['start_line', '!!!!'],
	 h5: ['start_line', '!!!!!'],
	 h6: ['start_line', '!!!!!!'],
	 ordered: ['start_lines', '#'],
	 unordered: ['start_lines', '*'],
	 indent: ['start_lines', '->'],
	 hr: ['line_alone', '----'],
	 link: ['bound_phrase', '[[', ']]'],
	 www: ['bound_phrase', '[[', ']]'],
	 bold: ['bound_phrase', "'''", "'''"],
	 code: ['bound_phrase', '@@', '@@'],
	 italic: ['bound_phrase', "''", "''"],
	 underline: ['bound_phrase', '{+', '+}'],
	 strike: ['bound_phrase', '{-', '-}'],   /* FIXME: not working so well */
	 ins: ['bound_phrase', '{+', '+}'],
	 del: ['bound_phrase', '{-', '-}'],   /* FIXME: not working so well */
	 big: ['bound_phrase', "'+", "+'"],
	 small: ['bound_phrase', "'-", "-'"],
	 sup: ['bound_phrase', "'^", "^'"],
	 sub: ['bound_phrase', "'_", "_'"],
}

proto.convertWikitextToHtml = function(wikitext, func) {
   var postdata = 'action=render&n=' + this.wikiwyg.pagename +
     '&text=' + encodeURIComponent(wikitext);
   Ajax.post(pmwiki.scripturl, postdata, func);
}

klass = Wikiwyg.Wikitext;

proto.format_sup = klass.make_formatter('sup');
proto.format_sub = klass.make_formatter('sub');
proto.format_ins = klass.make_formatter('ins');
proto.format_del = klass.make_formatter('del');
proto.format_big = klass.make_formatter('big');
proto.format_small = klass.make_formatter('small');

proto.format_br = function(element) {
     if (element.getAttribute('clear') == 'all') {
          this.appendOutput("[[<<]]");
     } else {
          this.appendOutput("\\\\\n");
     }
}

proto.format_img = function(element) {
    var uri = decodeURIComponent(element.getAttribute('src'));
    if (uri) {
       this.assert_space_or_newline();
       var attachment = this.get_attachment_name(uri);
       if (attachment) {
	  this.appendOutput('Attach:' + attachment);
       } else {
	  this.appendOutput(uri);
       }
       var alt = element.getAttribute('alt');
       if (alt) {
	  this.appendOutput('"' + alt + '"');
       }
    }
}

proto.get_attachment_name = function(uri) {
   if (pmwiki.uploads) {
      if (uri.indexOf(pmwiki.uploadpath) == 0) {
	 var thisattach = this.fmt_pagename(pmwiki.uploadprefix, this.wikiwyg.pagename);
	 var attachpart = uri.substr(pmwiki.uploadpath.length); /* path separator */
	 if (attachpart.indexOf(thisattach) == 0) {
	    return attachpart.substr(thisattach.length + 1);
	 } else {
	    // XXX: handle attachments from other pages or groups
	    return false;
	 }
      }
   }
   return false;
}

proto.fmt_pagename = function(fmt, fullname) {
   var parts = fullname.split('.');
   var result = fmt;
   result = result.replace(/\$Fullname/, fullname);
   result = result.replace(/\$Group/, parts[0]);
   result = result.replace(/\$Name/, parts[1]);
   return result;
}

proto.make_wikitext_link = function(label, href, element) {
     var before, after;

     this.assert_space_or_newline();
     if (! href) {
          var name = element.getAttribute('name');
          if (name) {
               this.appendOutput('[[#' + name + ']]');
          } else {
               this.appendOutput(label);
          }
     } else if (href == label) {
          this.appendOutput(href);
     } else if (this.href_is_wiki_link(href)) {
          before = this.config.markupRules.link[1];
          after  = this.config.markupRules.link[2];

          if (label == "?" && href.match(/action=edit$/)) {
               /* Automated broken-link link; ignore */
          } else if (this.camel_case_link(label))
               this.appendOutput(label);
          else {
               var fullname = this.get_wiki_link_pagename(href);
               if (this.label_match(fullname, label)) {
                    this.appendOutput(before + label + after);
               } else {
                    var parts = fullname.split('.');
                    var group = parts[0];
                    var page = parts[1];
                    var current_group = this.wikiwyg.pagename.split('.')[0];
                    if (this.label_match(page, label)) {
                         if (group == current_group) {
                              this.appendOutput(before + label + after);
		 } else {
              this.appendOutput(before + group + "/" + label + after);
		 }
                    } else {
                         /* XXX: [[Suffix]]es, [[DefaultPage/]], [[hidden stuff (in parentheses)]] */
                         this.appendOutput(before + label + ' -> ' + fullname + after);
                    }
               }
          }
    } else {
         var attach = this.get_attachment_name(decodeURIComponent(href));

         if (attach) {
              this.appendOutput("Attach:" + attach);
         } else  {
              before = this.config.markupRules.www[1];
              after = this.config.markupRules.www[2];

              this.appendOutput(before + label + ' -> ' + href + after);
         }
    }
}

proto.get_wiki_link_pagename = function(href) {
     var dhref = decodeURIComponent(href);
     var scriptlen = pmwiki.scripturl.length;

     if (pmwiki.pathinfo) {
          var urlform = dhref.substr(scriptlen + 1); // slash
          return urlform.replace(/\//, ".");
     } else {
          var argstring = dhref.substr(scriptlen + 1); // question mark
          var args = argstring.split(/[&\?]/);
          for (var i in args) {
               var arg = args[i];
               var argparts = arg.split("=");
               if (argparts[0] == 'n' || argparts[0] == 'pagename') {
                    return argparts[1];
               }
          }
          return '';
     }
}

proto.label_match = function(pagename, label) {
   return (pagename == this.wikiwyg.text_to_pagename(label));
}

proto.href_is_wiki_link = function(href) {
   var dhref = decodeURIComponent(href);
   return (dhref.indexOf(pmwiki.scripturl) == 0);
}

proto = new Subclass('Wikiwyg.Preview.PmWiki', 'Wikiwyg.Preview');

proto.fromHtml = function(html) {
    if (Wikiwyg.Wysiwyg.prototype.isPrototypeOf(this.wikiwyg.previous_mode) ||
	Wikiwyg.HTML.prototype.isPrototypeOf(this.wikiwyg.previous_mode))
     {
        var wikitext_mode = this.wikiwyg.mode_objects['Wikiwyg.Wikitext.PmWiki'];
        var self = this;
        wikitext_mode.convertWikitextToHtml(
            wikitext_mode.convert_html_to_wikitext(html),
            function(new_html) { self.div.innerHTML = new_html }
        );
    }
    else {
        this.div.innerHTML = html;
    }
}

proto = new Subclass('Wikiwyg.Wysiwyg.PmWiki', 'Wikiwyg.Wysiwyg');

proto.do_link = function() {
     var selection = this.get_link_selection_text();
     if (! selection) return;
     var url;
     var match = selection.match(/(.*?)\b((?:http|https|ftp|irc|file):\/\/\S+)(.*)/);
     if (match) {
          if (match[1] || match[3]) return null;
          url = match[2];
     }
     else {
          var pagename = this.wikiwyg.text_to_pagename(selection);
          var group = this.wikiwyg.get_current_group();
          url = this.wikiwyg.make_page_url(group, pagename);
     }
     this.exec_command('createlink', url);
}

