function extend(Child, Parent) {
  var F = function() { }
  F.prototype = Parent.prototype
  Child.prototype = new F()
  Child.prototype.constructor = Child
  Child.superclass = Parent.prototype
}

function MagicInput(options, data, callback) {
  this.data = data;
  this.options  = options;
  this._callback = callback;
}

MagicInput.prototype.toString = function() {
  return 'This is MagicInput object';
}

MagicInput.prototype.callback = function() {
  this._callback.apply(this, arguments);
}

MagicInput.instance = function(el, data, callback) {
  el = $(el);
  var options = {};
  options['action'] = el.attr('mi-action');
  options['title']  = el.attr('mi-title');
  options['iface']  = el.attr('mi-iface');
  options['data']   = el.attr('mi-data');
  try {
    $.extend(data, options.data ? $.parseJSON(options.data) : {});
    delete options.data;
    options.iface = 'mi' + options.iface.substring(0, 1).toUpperCase() + options.iface.substring(1);
    return input = new window[options.iface](options, data, callback);
  } catch(e) {
    console.log('MagicInput::instance ' + e);
    throw e;
  }
}

function miNone(options, callback) {
  miNote.superclass.constructor.apply(this, arguments);
  this.callback();
}
extend(miNone, MagicInput);

miNone.prototype.toString = function() {
  return 'This is miNone object';
}

function miNote(options, callback) {
  miNote.superclass.constructor.apply(this, arguments);
  if(confirm('Использовать "'+this.options.title+'" сейчас?')) {
    this.callback()
  }
}
extend(miNote, MagicInput);

miNote.prototype.toString = function() {
  return 'This is miNote object';
}

function miDialog(options, data, callback, content, dialogOptions) {
  miDialog.superclass.constructor.apply(this, arguments);
  var mi = this;
  this.dialog = content.dialog($.extend({}, {
   title: this.options.title,
   resizable: false,
   minHeight: 20,
   dialogClass: 'sand-style mi-container',
   beforeClose: function(e, ui) {
     var tmp = true;
     if(1 * $(this).attr('submit')) {
       mi._collect.call(mi);
       if(tmp = mi._validation.call(mi)) {
         return true;
       }
     }
     $(this).attr('submit', 0);
     return tmp;
   },
   close: function(e, ui) {
     if(1 * $(this).attr('submit')) {
       mi.callback();
     }
     mi.destroy();
   }
  }, dialogOptions)).on('click','.dialog-submit',function() { $(this).closest('.ui-dialog-content').attr('submit', 1).dialog('close')})
}

extend(miDialog, MagicInput);

miDialog.prototype.toString = function() {
  return 'This is ABSTRACT miDialog object';
}

miDialog.prototype.destroy = function() {
  this.dialog.dialog('destroy').remove();
}

miDialog._oneInput = function(p) {
  var i = $('<input type="'+(p.type ? p.type : 'text')+'" onkeyup="'+(p.onkeyup ? p.onkeyup : 'return false;')+'" onchange="'+(p.onchange ? p.onchange : 'return false;')+'" class="'+(p.clas ? p.clas : 'text')+'" value="'+(p.value ? p.value : '')+'" />').attr('name', p.name);
  if(p.grabber) {
    h[p.grabber].set(i);
  } else {
    i.select();
  }
  return $('<div class=oneinput></div>').append('<input type=button class="button dialog-submit" value=" »» ">').append($('<div></div>').append(i));
}

miDialog._hiddenInput = function(p) {
  var i = $('<input type="hidden" class="text" />').attr('name', p.name).attr('value', p.value);
  if(p.grabber) {
    h[p.grabber].set(i);
  } else {
    i.select();
  }
  return $('<div class=oneinput></div>').append($('<div></div>').append(i));
}

miDialog._simpleInput = function(p) {
  var i = $('<input type="'+(p.type ? p.type : 'text')+'" value="'+(p.value ? p.value : '')+'" class="text" />').attr('name', p.name);
  if(p.grabber) {
    h[p.grabber].set(i);
  } else {
    i.select();
  }
  return $('<div class=oneinput></div>').append($('<div></div>').append(i));
}

miDialog.prototype._collect = function() {
  var mi = this;
  this.dialog.find('[name]').each(function() {
    var el = $(this);
    if(el.is('input[type="checkbox"]')) {
      mi.data[el.attr('name')] = ~~el.is(':checked');
      return;
    }
    mi.data[el.attr('name')] = el.val();
  })
}

miDialog.prototype._validation = function() {
  return true;
}