// ==UserScript==
// @name           LJSupport: Category Detection
// @namespace      http://afunamatata.com/greasemonkey/
// @description    Add a button to make it easier to send a request to whichever category you choose
// @include        http://www.livejournal.com/support/see_request.bml?id=*
// @tags           ljsupport
// ==/UserScript==

/** 
 only check each category once?
 add more slots for filters
 let you export and import the entire filter set...
 customize number of filters you can have, but risk losing saved filters if you set the number too low...
 set to defaults button?
 categories as a drop down
 */ 
function detectCategory(text, catname, catid, regex)
{   
    search = new RegExp(regex,"i");
    if(search.test(text))                          
    {    
        mark = document.createElement("a");
        mark.href = "";
        mark.textContent = catname + "?";
        mark.title = "Select "+catname;
        mark.addEventListener("dblclick", function(event) 
            {
                changeCat.value = catid;
                document.getElementById('replytype').value='internal';
                changeCat.form.submit();
                
                event.stopPropagation();
                event.preventDefault();
            }, false);
            
        mark.addEventListener("click", function(event)
            {
                changeCat.value = catid;
                document.getElementById('replytype').value='internal';
                var textarea = document.getElementById("body");

                event.stopPropagation();
                event.preventDefault();
            }, false);
        insertionPoint.appendChild(document.createTextNode(" "));
        insertionPoint.appendChild(mark);
    }   
    
}

function createField(row, name, size) {
    var field = document.createElement("input");
    field.setAttribute('name', name+'[]');
    field.setAttribute('class', name);
    field.setAttribute('size', size);
    
    row.appendChild(field);
    return field;
}
function createButton(row, text, callback) {
    var button = document.createElement("button");
    button.appendChild(document.createTextNode(text));
    button.addEventListener('click', callback, false);
    
    row.appendChild(button);
    return button;
}
function createEditInterface() {
    GM_addStyle('#editInterface { position: fixed; bottom: 3em; right: 3em; background-color: #fff; border: 1px silver solid; padding: 2em; overflow: } #editInterface input {margin-bottom: 0.5em;} #editInterface .category {margin-left: 1.5em; margin-right: 0.5em;}  #editInterface div { float: left; } #editInterface #buttonRow {clear: left;}');

    var defaultFilters = [
        // sup, SUP, sUp! -- it's all good
        {'category':'SUP', 'value': "\\bSUP\\b|livejournal.ru"},
        
        // detect any URLs (http:// ... .htm) which don't mention livejournal or sixapart 
        // the latter more likely in ICs than in requests, so will likely have no effect, but hey.
        // doesn't detect urls that don't contain .html or .html; fall back on <a href detection
        {'category':'xx-spam', 'value': "http://(?![^\\s]*(?:livejournal|sixapart))[^\\s]+\\.htm|<a href="},
        
        // detect some common Cyrillic letters (need to consult someone who actually knows Cyrillic) (add it in manually! Gets mangled otherwise)
        {'category':'Russian Support', 'value': '[]'}
    ];

   
    var savedFilters = eval(GM_getValue("filters", null));
    if(!savedFilters || savedFilters.length == 0) {
        GM_setValue('filters', uneval(defaultFilters));
        savedFilters = defaultFilters;
        checkText();
    } 

    editInterface = document.createElement("div");
    var message = document.createElement("div");
    message.appendChild(document.createTextNode("Enter the search string as either a plain search term or a regex. Category names are case sensitive; search values are case-insensitive."));
    editInterface.appendChild(message);
    editInterface.setAttribute("id", "editInterface");
    filters = new Array(10);
    for (var i = 0, len=filters.length; i < len; i++) {
        
        row = document.createElement("div");
        editInterface.appendChild(row);
        filters[i] = {
            'category': createField(row, 'category', 10),
            'value' : createField(row, 'filter', 45),
        };
        
        if(savedFilters && savedFilters[i]) {
            filters[i]['category'].setAttribute('value', savedFilters[i]['category']);
            filters[i]['value'].setAttribute('value', savedFilters[i]['value']);
        } 
    }
    
    var row = document.createElement("div");
    row.setAttribute("id", "buttonRow");
    createButton(row, 'Save', saveEdit);
    createButton(row, 'Close', closeEdit);
    editInterface.appendChild(row);
    document.body.appendChild(editInterface);
    
}

function extractCategoryList() {
  var categoryList = new Object();
  var option;
  for(i = 0; i < changeCat.options.length; ++i) {
    option = changeCat.item(i);
    if(option.value != '')
      categoryList[option.textContent] = option.value;
  }
  
  return categoryList;
}

function destroyEditInterface() {
    document.body.removeChild(document.getElementById("editInterface"));
}
function openEdit(event) {
    createEditInterface();
    
    event.stopPropagation();
    event.preventDefault();
}
function isEmpty(text) {
    return text.replace(/^\s*$/g, '').length == 0;
}

function saveEdit() {
    categories = document.getElementsByName('category[]');
    values = document.getElementsByName('filter[]');
    var filters = new Array();
    for(var i = 0, len = categories.length; i < len; ++i ) {
        if(!isEmpty(categories[i].value) && !isEmpty(values[i].value))
            filters.push({'category': categories[i].value, 'value': values[i].value});
    }
    GM_setValue("filters", uneval(filters));
    //destroyEditInterface();
    checkText();
}

function closeEdit() {
    destroyEditInterface();
}

function checkText() {
    var filters = eval(GM_getValue("filters", null));
    if(!filters) return;
    // TODO: add more categories
    var categories = extractCategoryList();
   
    for (var i = 0, filter; filter = filters[i]; i++) {
        if(filter['category'] && filter['value'])
            detectCategory(text, filter['category'], categories[filter['category']], filter['value']);
    }

}

changeCat = document.getElementsByName("changecat")[0];
if(changeCat != null)
{
    var table = document.getElementsByTagName('table')[0]
    var tr = table.insertRow(-1); 
    var td = tr.insertCell(-1);
    td.align = "right";    
    td.style.fontWeight = "bold";
    
    var triggerEdit = document.createElement("a");
    triggerEdit.appendChild(document.createTextNode("Category detection"));
    triggerEdit.setAttribute("href", "");
    triggerEdit.addEventListener("click", openEdit, false);       
    td.appendChild(document.createTextNode(" "));
    td.appendChild(triggerEdit);
    td.appendChild(document.createTextNode(":"));
    
    insertionPoint = tr.insertCell(-1);

    text = document.evaluate("//div[@id='content-wrapper']//div//div", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent;

    checkText(); 
}
