
(function($) {
  
  $.fn.taurusRadio = function(name, options, checked) {
    
    var group = $('<div class="radioGroup" />');
    
    $.each(options, function(value, label) {
      var option = $('<span class="radioOption" />');
      var input = 
        $(_T('<input id="radioInput-#{n}-#{v}" type="radio" name="#{n}" value="#{v}" />', {
          n : name,
          v : value
        }));
      var label = 
        $(_T('<label for="radioInput-#{n}-#{v}">#{l}</label>', {
          n : name,
          v : value,
          l : label
        }));
      if (value == checked) {
        input.attr('checked', 'checked');
      }
      option.append(input).append(label).appendTo(group);
    });
    
    $(this).append(group);
  };

  $.fn.taurusCheckbox = function(name, options, checked) {
    
    var group = $('<div class="checkboxGroup" />');
    
    $.each(options, function(value, label) {
      var option = $('<span class="checkboxOption" />');
      var input = 
        $(_T('<input id="checkboxInput-#{n}-#{v}" type="checkbox" name="#{n}" value="#{v}" />', {
          n : name,
          v : value
        }));
      var label = 
        $(_T('<label for="checkboxInput-#{n}-#{v}">#{l}</label>', {
          n : name,
          v : value,
          l : label
        }));
      if (checked && Array.contains(checked, value)) {
        input.attr('checked', 'checked');
      }
      option.append(input).append(label).appendTo(group);
    });
    
    $(this).append(group);
  };
  
  $.fn.taurusSelect = function(name, options, selected, params) {
    
    params = params || {};
    
    var select = $(_T('<select name="#{n}" class="selectGroup" />', { n : name }));
    
    if (params['caption']) {
      var option = $(_T('<option class="selectOption" value="">#{l}</option>', { 
        l : params['caption'] 
      }));
      option.appendTo(select);
    }

    $.each(options, function(value, label) {
      var option = $(_T('<option class="selectOption" value="#{v}">#{l}</option>', {
        v : value,
        l : label
      }));
      if (selected && selected == value) {
        option.attr('selected', 'selected');
      }
      option.appendTo(select);
    });
    
    $(this).append(select);
  };
  
  var getSortableIds = function(selector, prefix) {
    var ids = [];
    $(selector).each(function() {
      $(this).attr('id').match(new RegExp(prefix + '-(\\d+)'));
      ids.push(parseInt(RegExp.$1));
    });
    return (ids.length == 0) ? "[]" : $.toJSON(ids);
  };
    
  $.fn.taurusSortableTable = function(saveUrl, options) {

    var itemsSelector = '#' + $(this).attr('id') + ' tr.sortItem';
    var oldIds = getSortableIds(itemsSelector, options['prefix']);
    
    $(this).find('tbody').sortable({
      items: 'tr.sortItem',
      handle: 'td.sortHandler',
      cursor: 'move',
      stop: function() {
        var newIds = getSortableIds(itemsSelector, options['prefix']);
        if (oldIds == newIds) {
          return;
        }
        var ajaxParams = {
          oldValue : oldIds,
          newValue : newIds
        };
        $.ajax({
          url : saveUrl,
          type : 'POST',
          dataType : 'json',
          data : ajaxParams,
          success : function(data) {
            if (data.isError) {
              // do something.
              return;
            }
            oldIds = getSortableIds(itemsSelector, options['prefix']);
            if (options['onSaveComplete']) {
              options['onSaveComplete']($.parseJSON(data.result));
            }
          }
        });
      }
    });
  };
  
  var miso = {

    urlInputPanel : null,

    defaultOptions : {
      addActionUrl: 'you must specify the parameter "addActionUrl"',
      deleteActionUrl: 'you must specify the parameter "deleteActionUrl"',
      popupLinkLabel: '追加',
      deleteLinkLabel: '&nbsp;&nbsp;&nbsp;',
      urlInputMessage: '記事または連載のURLを入力してください',
      urlInputFieldFinishButton: '確定',
      urlInputFieldCancelButton: 'キャンセル',
      errorAccessFailed: 'サーバに接続できません',
      errorUrlNotFound: '#{url} が見つかりません',
      errorUrlAlreadyAdded: '#{url} は追加済みです'
    },
    
    setupUrlInputPanel: function(opt) {
      if (miso.urlInputPanel) {
        return;
      }
      miso.urlInputPanel = $('<div id="misoUrlInputPanel" />')
        .css('position', 'absolute')
        .css('display', 'none');
      var misoUrlInputMessage = $(_T('<p id="misoUrlInputMessage">#{msg}</p>', { 
        msg : opt['urlInputMessage'] 
      }));
      var misoUrlInputField = $('<p id="misoUrlInput" />')
        .append($('<input id="misoUrlInputField" type="text" />'));
      var misoUrlInputActionButtons = $('<p id="misoUrlInputActionButtons" />')
        .append($(_T('<input id="misoUrlInputFinishButton" type="button" value="#{l}" />', { 
          l : opt['urlInputFieldFinishButton'] 
        })))
        .append($(_T('<input id="misoUrlInputCancelButton" type="button" value="#{l}" />', { 
          l : opt['urlInputFieldCancelButton'] 
        })));
      
      miso.urlInputPanel.append(misoUrlInputMessage);
      miso.urlInputPanel.append(misoUrlInputField);
      miso.urlInputPanel.append(misoUrlInputActionButtons);
      $('body').append(miso.urlInputPanel);
      
      miso.urlInputPanel.draggable({
        cursor: 'move'
      });

      $('#misoUrlInputCancelButton').bind('click', function() {
        $('#misoUrlInputField').val('');
        miso.urlInputPanel.fadeOut('fast');
        return false;
      });
    },
    
    createPostEntry: function(id, title, opt) {
      var post = $(_T('<li id="misoPostItem-#{id}">', { id : id })).addClass('misoPostItem');
      var postTitle = $(_T('<span id="misoPostItemLabel-#{id}">#{title}</span>', {
        id : id,
        title : title
      })).addClass('misoPostItemLabel');
      var postDeleteLink = $(_T('<a id="misoPostItemDeleteLink-#{id}" href="#">#{deleteLabel}</a>',{
        id : id,
        deleteLabel : opt['deleteLinkLabel']
      })).addClass('misoPostItemDeleteLink');
      
      postDeleteLink.bind('click', function() {
        $.ajax({
          url : opt['deleteActionUrl'],
          type : 'POST',
          dataType : 'json',
          data : { id: id },
          success : function(data) {
            if (data.isError) {
              alert(data.errorText);
              return;
            }
            post.fadeOut('slow', function() {
              post.remove();
            });
          },
          error : function() {
            alert(_T(opt['errorAccessFailed']));
          }
        });
        return false;
      });

      return post.append(postTitle).append(postDeleteLink);
    }

  };
  
  $.fn.taurusMiso = function(options) {

    var opt = $.extend({}, miso.defaultOptions, options);
    miso.setupUrlInputPanel(opt);

    var self = $(this);
    var id = self.attr('id');

    var panel = $(_T('<div id="misoPanel-#{id}" />', { id : id })).addClass('misoPanel');
    var postList = $(_T('<ul id="misoPostList-#{id}" />', { id : id })).addClass('misoPostList');
    var popupLink = $(_T('<a id="misoPopupLink-#{id}" href="#">#{l}</a>', { 
      id : id, 
      l : opt['popupLinkLabel'] 
    })).addClass('misoPopupLink');
    
    panel.append(postList).append(popupLink).appendTo(self);
    
    if (opt['initialData']) {
      $.each(opt['initialData'], function (id, title) {
        postList.append(miso.createPostEntry(id, title, opt));
      });
    }
    
    popupLink.bind('click', function(e) {
      $('#misoUrlInputFinishButton').unbind('click');
      $('#misoUrlInputFinishButton').bind('click', function() {
        $('#misoUrlInputFinishButton').attr('disabled', 'disabled');
        var ajaxParams = $.extend({}, opt['data'], {
          postUrl : $('#misoUrlInputField').val().strip()
        });
        $.ajax({
          url : opt['addActionUrl'],
          type : 'POST',
          dataType : 'json',
          data : ajaxParams,
          success : function(data) {
            if (data.isError) {
              alert(data.errorText);
              return;
            }
            var result = $.parseJSON(data.result);
            var post = miso.createPostEntry(result.id, result.title, opt);
            miso.urlInputPanel.fadeOut('fast', function() {
              $('#misoUrlInputField').val('');
              postList.append(post);
              post.effect('highlight', {}, 1500);
            });
          },
          error : function() {
            alert(_T(opt['errorAccessFailed']));
          },
          complete : function() {
            $('#misoUrlInputFinishButton').removeAttr('disabled');
          }
        });
      });
      miso.urlInputPanel.fadeOut(150, function() {
        miso.urlInputPanel.css('top', e.pageY);
        miso.urlInputPanel.css('left', e.pageX);
        miso.urlInputPanel.fadeIn(150);
      });
      return false;
    });

  };

})(jQuery);
