(function($){

  $.fn.formElements = function(options){

    var element = this;

    var select_iterator = 0;

    var elements = {

      custom_class: 'customized',
      active_class: 'active',
      select_class: {
        cur_selection: 'cur_sel',
        option_list: 'opt-list',
        list_item: 'list-item',
        top_opt_list: 1,
        custom_html: '<span class="opt-list-bottom"></span>'
      },

      init: function(){

        var sel_merge = {};
        if(typeof(options) != 'undefined') $.extend(sel_merge, elements.select_class, options.select_class);
        $.extend(elements, options);
        $.extend(elements.select_class, sel_merge);

        element.each(function(){

          switch($(this).attr('type')){

            case 'checkbox':
              elements.checkbox($(this));
              break;

            case 'radio':
              elements.radio($(this));
              break;

            default:
              if($(this).is('select')) elements.select($(this));
              break;

          }
        })

      },

      checkbox: function(c_element){
        var checkbox_suffix = '-checkbox';

        var span_block = $('<span />',{
          'rel': c_element.attr('name')+'.'+c_element.val()
        });
          
        span_block.addClass(elements.custom_class+checkbox_suffix);

        $.map(c_element.attr('class').split(' '), function(val){       
          span_block.addClass(val)
        });

        

        if(c_element.attr('checked') === 'checked' || c_element.prop('checked') === true){
          span_block.addClass(elements.active_class)
        }

        c_element.change(function(){
          if(c_element.attr('checked') === 'checked' || c_element.prop('checked') === true){            
            span_block.addClass(elements.active_class)
          }
          else{
            span_block.removeClass(elements.active_class)
          }
        })

        span_block.click(function(){         
          if(span_block.hasClass(elements.active_class)){
            span_block.removeClass(elements.active_class);
            $('[name='+span_block.attr('rel').split('.')[0]+'][value='+span_block.attr('rel').split('.')[1]+']').removeAttr('checked');
          }
          else{           
            span_block.addClass(elements.active_class);
            $('[name='+span_block.attr('rel').split('.')[0]+'][value='+span_block.attr('rel').split('.')[1]+']').attr('checked', 'checked');             
          }
          $(c_element).change();
        })
        
        c_element.before(span_block);
        c_element.hide();

      },

      radio: function(c_element){
        var radio_suffix = '-radio';

        var span_block = $('<span />',{
          'rel': c_element.attr('name')
        });
          
        span_block.addClass(elements.custom_class+radio_suffix);
        $.map(c_element.attr('class').split(' '), function(val){
          span_block.addClass(val)
        });

        if(c_element.attr('checked') == true){
          span_block.addClass(elements.active_class)
        }

        c_element.change(function(){
          if(c_element.attr('checked') == true){
            $('[rel='+c_element.attr('name')+']').removeClass(elements.active_class);
            span_block.addClass(elements.active_class)
          }
        })

        span_block.click(function(){

          if(!span_block.hasClass(elements.active_class)){            
            $('[rel='+c_element.attr('name')+']').removeClass(elements.active_class);
            span_block.addClass(elements.active_class);
            $(c_element).attr('checked', 'checked');
            $(c_element).change();
          }
          
        })

        c_element.before(span_block);
        c_element.hide();

      },

      select: function(c_element){

        var select_suffix = '-select';

        //Generating blocks
        var select_block = $('<span />', {
          'rel': c_element.attr('name'), 
          'class': elements.custom_class+select_suffix
          });
        var curr_select = $('<span />', {
          'class': elements.select_class.cur_selection
          });
        var opt_list = $('<span />', {
          'class': elements.select_class.option_list,
          css: {
            'position': 'absolute',
            'width': select_block.width()
          } 
        });        
        $('option', c_element).each(function(){
          opt_list.append('<span class="'+elements.select_class.list_item+'" rel="'+$(this).val()+'">'+$(this).text()+'</span>')
        })
        $.map(c_element.attr('class').split(' '), function(val){
          select_block.addClass(val)
        });
        
        opt_list.append(elements.select_class.custom_html);
        curr_select.text($('option:selected', c_element).text())
        select_block.append(curr_select)
        $('body').append(opt_list);

        c_element.before(select_block).hide();
        opt_list.css('font-size', parseInt(select_block.css('font-size')))
        opt_list.width(parseInt(select_block.width())+parseInt(select_block.css('padding-left'))+parseInt(select_block.css('padding-right')))
        $('.list-item', opt_list).css('padding-left', parseInt(select_block.css('padding-left')))
        select_block.attr('id', 'select_'+select_iterator);
        opt_list.attr('id', 'opt_list_'+select_iterator);
        select_iterator++;
        
        
        opt_list.hide();

        
        //Adding events
        $('body').click(function(){
          $('.'+elements.select_class.option_list).hide();
        })
        
        $(window).resize(function(){
          $('.'+elements.select_class.option_list).hide();
        });

        select_block.click(function(event){
          event.stopPropagation();

          var sel_pos = $(this).offset();
          opt_list.css({
            top: (sel_pos.top+parseInt(select_block.height())+elements.select_class.top_opt_list)+'px', 
            left: sel_pos.left+'px'
            });

         if(opt_list.css('display') === 'block'){
           opt_list.hide();
         }
         else{
           opt_list.show();
         }
        })

        $('.'+elements.select_class.list_item).click(function(){          
          var rel = $('#select_'+$(this).parent().attr('id').split('opt_list_')[1]).attr('rel');
          $('[name='+rel+'] option').attr('selected', '');
          $('[name='+rel+'] option[value='+$(this).attr('rel')+']').attr('selected', 'selected');
                    
          $('#select_'+$(this).parent().attr('id').split('opt_list_')[1]).children('.'+elements.select_class.cur_selection).text($(this).text());
          
          $(c_element).change();
        })

      }

    }

    elements.init();

  }

})(jQuery)
