var common = (function() {

    var overlay = function(options) {
        options = options || {};

        if (!options.url && !options.html) {
            return;
        }

        if (!common.overlay.initialized) {
            common.overlay.initialize();
        }

        var onShow = overlay.show;

        if (options.onShow) {
          onShow = function() {
            if (options.onShow() !== false) {
              overlay.show();
            }
          }
        }

        if (options.html) {
            overlay.content.html(options.html);
            if (!options.url) onShow();
        }
        if (options.url) {
            overlay.content.load(options.url, onShow);
        }

        overlay.modal = options.modal || false;
        return false;
    };
    overlay.close = function() {
        overlay.overlay.trigger('close');
        overlay.box.animate({'top':'-' + (100 + overlay.box.height()) + 'px'}, 500,
          function() {
              overlay.overlay.fadeOut('fast');
          });
        return false;
    }
    overlay.show = function() {
        overlay.overlay.fadeIn('fast', function() {
            var top = $(window).scrollTop() + ((overlay.box.height() + 40) >= $(window).height() ? 0 : 30);
            overlay.box.animate({'top':top}, 300);
        });
        return false;
    }
    overlay.initialized = false;
    overlay.initialize = function() {
        overlay.overlay = $('<div />').
          attr('id', 'overlay_global').
          css('display', 'none').
          click(function() {
            !common.overlay.modal && common.overlay.close();
        });

        overlay.box = $('<div />').
          attr('id', 'overlay_box');

        overlay.boxclose = $('<div />').
          attr('id', 'overlay_boxclose').
          click(function() {
            common.overlay.close()
        });
        overlay.content = $('<div />').
          attr('id', 'overlay_content');

        overlay.box.append(overlay.boxclose).append(overlay.content);
        overlay.box.append(overlay.content);
        $('body').append(overlay.overlay).append(overlay.box);
        overlay.initialized = true;
    }

    var highlight = function(obj, startColor, endColor) {
        if ($.fx.off) return;

        obj = $(obj).stop(true, true);
        startColor = startColor || '#ffd';

        endColor = endColor || obj.css('backgroundColor');
        obj.css('backgroundColor', startColor).animate({backgroundColor: endColor}, 600);
    }

    var tab = function(a) {
        var link = $(a), links = link.closest('ul').find('a'), divs = [];

        links.parents().removeClass('active');
        for (var i = 0; i < links.length; i++) {
            divs.push($('#' + links[i].getAttribute('rel')));
        }

        for (i = 0; i < divs.length; i++) {
            if (divs[i].attr('id') == a.getAttribute('rel')) {
                divs[i].show();
                link.parent().addClass('active');
            } else {
                divs[i].hide();
            }
        }
        return false;
    }

    var flashes = null;
    var flash = function (message, type) {
        type = type || 'warning';

        var div = $('<div/>');

        div.addClass(type).css({'display':'none'}).html(message);

        if (!flashes) {
            flashes = $('#flashes');
        }

        flashes.html('').append(div);
        div.fadeIn();
    }

  function json_encode(arr) {
    var json, value,
      parts = [],
      is_list = (Object.prototype.toString.apply(arr) === '[object Array]');
    for (var key in arr) {
      value = arr[key];

      if (typeof value == "object"/* && value !== null*/) { //Custom handling for arrays
        if (is_list) parts.push(json_encode(value)); /* :RECURSION: */
        else parts[key] = json_encode(value);
        /* :RECURSION: */
      } else {
        var str = "";
        if (!is_list) str = '"' + key + '":';

        //Custom handling for multiple data types
        if (typeof value == "number") str += value; //Numbers
        else if (value === false) str += 'false'; //The booleans
        else if (value === true) str += 'true';
        else if (value === null) str += 'null';  // FOR NULL
        else str += '"' + value.replace(/"/g, "\\\"") + '"'; //All other things
        // :TODO: Is there any more datatype we should be in the lookout for? (Functions?)

        parts.push(str);
      }
    }
    json = parts.join(",");

    if (is_list) return '[' + json + ']';//Return numerical JSON
    return '{' + json + '}';//Return associative JSON
  }

  return {
    overlay: overlay,
    highlight: highlight,
    tab: tab,
    flash: flash,
    json: json_encode
  }
})();

(function($) {

    $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i, attr) {
        $.fx.step[attr] = function(fx) {
            if (fx.state == 0) {
                fx.start = getColor(fx.elem, attr);
                fx.end = getRGB(fx.end);
            }

            fx.elem.style[attr] = "rgb(" + [
                Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
                Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
                Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
            ].join(",") + ")";
        }
    });

    function getRGB(color) {
        var result;

        // Check if we're already dealing with an array of colors
        if (color && color.constructor == Array && color.length == 3)
            return color;

        // Look for rgb(num,num,num)
        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
            return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];

        // Look for rgb(num%,num%,num%)
        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
            return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55];

        // Look for #a0b1c2
        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
            return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)];

        // Look for #fff
        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
            return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)];

        return [ 255, 255, 255 ];
    }

    function getColor(elem, attr) {
        var color;

        do {
            color = $.curCSS(elem, attr);

            // Keep going until we find an element that has color, or we hit the body
            if (color != '' && color != 'transparent' || $.nodeName(elem, "body"))
                break;

            attr = "backgroundColor";
        } while (elem = elem.parentNode);

        return getRGB(color);
    }

    $.pop = function(container, options) {
        var me = this;

        var $container = $(container);

        container.pop = me;

        // settings
        var settings = {
            pop_toggle_text : ''
        }

        // inject html wrapper
        var pop_classes = $container.attr("class");
        $container.wrap("<div class='pop " + pop_classes + "'></div>");
        $container.attr("class", "pop_menu");
        $container.before("<div class='pop_toggle'>" + settings.pop_toggle_text + "</div>");

        var $wrapper = $container.parent();

        // toggle that pop
        $wrapper.find(".pop_toggle").click(function() {
            is_active = $wrapper.hasClass("pop_active");
            $('.pop_active').removeClass('pop_active');
            if(is_active)
                $wrapper.removeClass("pop_active");
            else
                $wrapper.addClass("pop_active");
        });

        this.container = $wrapper;

        this.close = function() {
            $wrapper.removeClass('pop_active');
            return me;
        }
        this.open = function() {
            $wrapper.addClass('pop_active');
            return me;
        }

    }

    $.fn.pop = function() {
        this.each(function() {
            new $.pop(this, {});
        });
        return this;
    }

    $.placeholder = function (input, color) {
      if (!input) return null;
      var _input = $(input);
      if (input.placeholder && 'placeholder' in document.createElement(input.tagName)) return _input;
      var placeholder_color = color || '#aaa';
      var default_color = input.style.color;
      var placeholder = _input.attr('placeholder');

      if (input.value === '' || input.value == placeholder) {
        input.value = placeholder;
        input.style.color = placeholder_color;
      }
      _input.focus(function() {
        this.style.color = default_color;
        if (this.value == placeholder) {
          this.value = '';
        }
      });

      _input.blur(function() {

        if (this.value === '' || this.value === placeholder) {
          this.value = placeholder;
          this.style.color = placeholder_color;
        } else {
          this.style.color = default_color;
        }
      });

      input.form && $(input.form).submit(function() {
        if (input.value == placeholder) {
          input.value = '';
        }
      });

      return _input.blur();
    }

    $.fn.placeholder = function(color) {
        this.each(function() {
            new $.placeholder(this, color);
        });
        return this;
    }

})(jQuery);


// other common tetradka fix
$(document).ready(function () {
  var list = $('div.sf_admin_list'),
      content = $('#sf_admin_content'),
      form = content.find('form'),
      filter = $('.sf_admin_filter'),
      actions = $('ul.sf_admin_actions');

  actions.addClass('admin_actions_list');


  if (list.length && form.length) {
      actions.prependTo(form);
  } else
  if (list.length) {
      actions.prependTo(content);
  }

  if (filter.length) {
      actions.prepend('<li class="sf_admin_action_filter"><a href="#" onclick="$(\'.sf_admin_filter\').toggle(); return false;">'+global_filter_name+'</a></li>');
      filter.append('<a class="filter_close" href="#" onclick="$(\'.sf_admin_filter\').toggle(); return false;"></a>');
      filter.hide();
  }
  
  $('.sf_admin_action_generateguarduserforstudent').click(function(){
      return confirm('Сгенерировать новые пароли для всех учеников?');
  })
  $('.sf_admin_action_generateguarduserforteacher').click(function(){
      return confirm('Сгенерировать новые пароли для всего персонала?');
  })
  
    ////////////////////
    // START: Липкие шапки таблиц
    // Копирование шапок таблиц в отдельный div
    $('table.table_with_fly_head').each(function(){
        $(this).wrap('<div class="table_with_fly_head_wrapper" />');
        $(this).removeClass('table_with_fly_head');
        var headElem = $('<table />').attr('class', $(this).attr('class')).addClass('fly_table_head').prepend($('thead', this).clone()).css({
            'position' : 'fixed',
            'top' : '-5000px',
            'z-index': 1010,
            'box-shadow': 'rgba(0, 0, 0, 0.5) 0px 2px 12px -4px'
        });
        $(this).parent().prepend(headElem);
        
        setTablesFlyHeaderWidth(headElem, this);
    });
  
  // Обработка скролла и ресайза окна, позиционарование летающие шапки
    $(window).bind('scroll resize', function () {
        var windowScrollTop = $(window).scrollTop();
        var windowScrollLeft = $(window).scrollLeft();
        $('.fly_table_head').each(function(){
            var elem = $(this);
            var parentElem = elem.parent();
            // Расстояние от верхней границы окна до верхней границы таблицы
            var topPos = windowScrollTop - parentElem.position().top;
            // Расстояние от нижней границы шапки до жиней границы таблицы + 5px
            // (5px просто чтобы пропадала чуть дальше таблицы, так приятнее смотрится)
            var bottomPos = windowScrollTop + elem.height() - parentElem.position().top - parentElem.height() - 5 ;
            if (topPos > 0 && bottomPos < 0)
            {
                elem.css('width', parentElem.width());
                elem.css('top', 0);
                elem.css('left', parentElem.position().left - windowScrollLeft);
            }
            else
            {
                elem.css('top', -5000);
            }
        });
    });
    $(window).resize(function(){
        $('.fly_table_head').each(function(){
            setTablesFlyHeaderWidth(this);
        });
    });
    // END: Липкие шапки таблиц
    ////////////////////
});

/**
 * Устанавливает ширину колонок летающей шапки таблицы в соотвествии с ее таблицой-мамочкой,
 * над которой она летает.
 * @param flyHeader Летающая шапка (.fly_table_head)
 * @param table [optional] Таблица, над которой летает шапка
 */
function setTablesFlyHeaderWidth(flyHeader, table)
{
    if (table == undefined)
    {
        table = $(flyHeader).parent().children()[1];
    }
    if (table != undefined)
    {
        var tableTheadThs = $('thead > tr > th', table);
        $('thead > tr > th', flyHeader).each(function(index){
            $(this).css('width', $(tableTheadThs[index]).width() + 'px')
        });
    }
}
