// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

var Brash = {};

Brash.Util = {
  auth_token: function() {
    return $('authenticity_token').value;
  },
  auth_token_param: function() {
    return "authenticity_token="+Brash.Util.auth_token();
  },
  auth_token_element: function() {
    return new Element('input',{type:'hidden',name:'authenticity_token',value:Brash.Util.auth_token()});
  },
  validate_integer: function(el) {
    var value = $F(el);
    var regInteger = new RegExp(/^\d+$/);
    return regInteger.test(value);
  },
  validate_float: function(el) {
    var value = $F(el);
    var regFloat = new RegExp(/^\d+(.\d\d)?$/);
    return regFloat.test(value);
  },
  validate_nonblank: function(el) {
    var value = $F(el);
    return !value.strip().blank();
  }
};

Brash.UI = {
  show_progress: function() {
    $('progress').show();
  },
  hide_progress : function() {
    $('progress').hide();
  },
  focus_first : function(form) {
    var error = form.down('.fieldWithErrors');
    var el;
    if(error) {
      form = error;
    }
    el = form.select('input[type="text"]','input[type="password"]').first();
    if(el) {
      el.select();
    }
  }
};

Brash.UI.Filter = Class.create({
  initialize : function(form, fields) {
    this.fields = fields;
    form.observe('submit', this.filter.bind(this));
    this.fields.each(function(f){
      var el = $(f);
      switch(el.tagName.toLowerCase()) {
      case 'select':  
        el.observe('change', this.filter.bindAsEventListener(this));
        break;
      case 'input':
        switch(el.type) {
        case 'checkbox':
          el.observe('change', this.filter.bindAsEventListener(this));
          break;
        case 'text':
          el.observe('focus', this.text_focus.bindAsEventListener(this));
          break;
        }
        break;
      };
    }.bind(this));
  },
  text_focus : function(event) {
    var el = event.element();
    var val = el.getValue();
    if(val===el.__brashPrompt) {
      el.value = '';
    }
    el.select();
  },
  set_prompt : function(el, prompt) {
    el.__brashPrompt = prompt;
    
    el.observe('blur', function(event) {
      var el = event.element();
      var val = el.getValue();
      if(val.blank()) {
        el.value = el.__brashPrompt;
      }
    });
    
    if(el.getValue().blank())
      el.value = el.__brashPrompt;
  },
  filter : function(event) {
    var args = [];
    event.stop();
    this.fields.each(function(f) {
      var el = $(f);
      if(el.type==='checkbox') {
        if(!el.checked)
          return;
      }
      else if($F(f).blank()||($F(f)===$(f).__brashPrompt)) {
        return;
      }
      else if($F(f)==='any') {
        return;
      }
      args.push($(f).serialize());
    });
    this.path = event.findElement('form').action;
    if(args.length>0)
      this.path += "?"+args.join('&');
    
    this.submit();
  },
  submit : function() {
    document.location = this.path;
  }
});

Brash.Assorter = {};
Brash.Assorter.Index = {
  init : function() {
    $('content').select('a.destroy').invoke('observe', 'click', Brash.Assorter.Index.do_destroy);
    var handler = new Brash.UI.Filter($('filter'), ['name','state']);
    handler.set_prompt($('name'), 'Find by name or comment...');
  },
  do_destroy : function(event) {
    var form;
    event.stop();
    if(!confirm("Are you sure you want to delete this Assorter")) {
      return;
    }
      
    form = new Element('form', {action:event.element().href, method:'post'}).update(Brash.Util.auth_token_element());
    event.findElement('div.assorters').insert({top:form});
    form.submit();
  }
};

Brash.Assorter.Settings = {
  init: function() {
    $('state').select('a.button').invoke('observe', 'click', Brash.Assorter.Settings.status_click);
    Brash.Assorter.Settings.show_description();
  },
  status_click: function(event) {
    event.stop();
    $('state').select('a.button').invoke('removeClassName', 'current');
    $('ad_state').value = event.findElement().name;
    event.element().addClassName('current');
    Brash.Assorter.Settings.show_description();
  },

  show_description : function() {
    $$('p.status_description').invoke('hide');
    $('status_'+$F('ad_state')).show();
  }
};

Brash.Assorter.Composer = {
  init: function() {
    // bind the whole page
    Brash.Assorter.Composer.bind_links($('content'));
    Brash.Assorter.Composer.bind_sortables($('content'));
  },
  bind_links: function(container) {
    container.select('a.edit').invoke('observe', 'click', Brash.Assorter.Composer.do_edit);
    container.select('a.new').invoke('observe', 'click', Brash.Assorter.Composer.do_new);
    container.select('a.destroy').invoke('observe', 'click', Brash.Assorter.Composer.do_destroy);
  },
  bind_sortables : function(container) {
    var sortables;
    
    sortables = container.select('a.sort.choices');
    sortables.each(function(a){
      var container = a.up('li.question').down('ul.choices');
      Sortable.create(container.id,{handle:'drag',scroll:window,onUpdate:function(container){
        new Ajax.Request(a.href,{parameters:Sortable.serialize(container.id)+"&"+Brash.Util.auth_token_param()})
      }});
    });

    sortables = container.select('a.sort.question');
    if(sortables.first()) {
      Sortable.create('questions',{handle:'drag',scroll:window,onUpdate:function(container){
        new Ajax.Request(sortables.first().href,{parameters:Sortable.serialize(container.id)+"&"+Brash.Util.auth_token_param()})
      }});
    }
  },
  do_edit: function(event) {
    var target;
    event.stop();
    Brash.UI.show_progress();
    target = event.findElement('ul.links').up('li').down('.settings');
    new Ajax.Request(event.element().href, {
        method:'get',
        onComplete:Brash.UI.hide_progress,
        onSuccess:Brash.Assorter.Composer.after_edit.bind(target)
      }
    );
  },
  after_edit: function(t) {
    var form, cancel;
    this.update(t.responseText);
    form = this.down('form');
    cancel = this.down('a.cancel');
    form.observe('submit', Brash.Assorter.Composer.do_update.bind(this));
    cancel.observe('click', Brash.Assorter.Composer.do_cancel.bind(this));    

    Brash.UI.focus_first(form);

    new Effect.Highlight(this);
  },
  do_cancel: function(event) {
    event.stop();
    Brash.UI.show_progress();
    
    new Ajax.Request(event.element().href, {
      method:'get',
      onComplete:Brash.UI.hide_progress,
      onSuccess:function(t) {
        this.update(t.responseText);
      }.bind(this)
    })
  },
  do_update: function(event) {
    event.stop();
    Brash.UI.show_progress();
    new Ajax.Request(event.element().action, {
        parameters:event.element().serialize(),
        onComplete:Brash.UI.hide_progress,
        onSuccess:Brash.Assorter.Composer.after_update.bind(this, false),
        onFailure:Brash.Assorter.Composer.after_update.bind(this, true)
      }
    );
  },
  after_update: function(failed, t) {
    if(failed) {
      Brash.Assorter.Composer.after_edit.bind(this, t).call();
    }
    else {
      this.update(t.responseText);
      new Effect.Highlight(this);
    }
  },
  do_new: function(event) {
    var collection = undefined;
    var el;
    event.stop();
    if(event.element().hasClassName('question'))
      collection=event.findElement('ul').nextSiblings().first();
    if(event.element().hasClassName('choice'))
      collection=event.findElement('li.question').down('ul.choices');
    
    el = collection.down('li.new');
    if(!el) {
      // create the new element and insert
      el = new Element('li',{'class':'new'});
      collection.insert({top:el});
    }
    
    Brash.UI.show_progress();
    new Ajax.Request(event.element().href,{
        method:'get',
        onComplete:Brash.UI.hide_progress,
        onSuccess:Brash.Assorter.Composer.after_new.bind(el, false)
      }
    );
  },
  after_new : function(failed, t) {
    var form, cancel, el;
    this.update(t.responseText);
    form = this.down('form');
    cancel = this.down('a.cancel');
    form.observe('submit', Brash.Assorter.Composer.do_create.bind(this));
    cancel.observe('click', function(event){event.stop(); event.findElement('li.new').remove();});
    
    Brash.UI.focus_first(form);
    new Effect.Highlight(this);
  },
  do_create: function(event) {
    event.stop();
    Brash.UI.show_progress();
    new Ajax.Request(event.element().action, {
        parameters:event.element().serialize(),
        onComplete:Brash.UI.hide_progress,
        onSuccess:Brash.Assorter.Composer.after_create.bind(this, false),
        onFailure:Brash.Assorter.Composer.after_new.bind(this, true)
      }
    );
  },
  after_create: function(failed, t) {
    var container;
    var insert;
    if(failed) {
      Brash.Assorter.Composer.after_new.bind(this, t).call();
    }
    else {
      // remove the li.new
      container = this.up('ul');
      this.remove();
      
      // insert the new element and retrieve it
      container.insert({bottom:t.responseJSON.html});
      
      insert = $(t.responseJSON.id);

      Brash.Assorter.Composer.bind_links(insert);
      
      insert.scrollTo();
      
      new Effect.Highlight(insert);
      
      Brash.Assorter.Composer.bind_sortables($('content'));
    }
  },
  do_destroy: function(event) {
    var form;
    var what;
    if(event.element().hasClassName('question'))
      what = 'question';
    else if(event.element().hasClassName('choice'))
      what = 'choice';
    var el;
    
    event.stop();
    
    if(!confirm('Are you sure you want to delete this '+what+'?'))
      return false;
      
    // Send an AJAX call and delete the element if a choice. If its a question
    // or question set, we do a traditional submit and re-render the page.
    switch(what) {
    case 'question':
      form = new Element('form', {action:event.element().href, method:'post'}).update(Brash.Util.auth_token_element());
      event.findElement('li').insert({top:form});
      form.submit();
      break;
    case 'choice':
      el = event.findElement('li.choice');
      new Ajax.Request(event.element().href,{parameters:Brash.Util.auth_token_param()});
      new Effect.Highlight(el);
      el.remove();

      Brash.Assorter.Composer.bind_sortables(el.up('li.question'));

      break;
    }
  }
}

Brash.Assorter.Responses = {
  init : function() {
    var handler = new Brash.UI.Filter($('filter'), ['size','token']);
    handler.submit = function() {
      Brash.UI.show_progress();

      $('filtered_report').update(new Element('p').update('Please wait while we retrieve your results.'));
      
      new Ajax.Request(this.path, {
        method:'get',
        onComplete:Brash.UI.hide_progress,
        onSuccess:this.show_response
      });
    }
    $$('a.filter').invoke('observe', 'click', Brash.Assorter.Responses.get_filtered_responses);
  },
  get_filtered_responses : function(event) {
    event.stop();
    Brash.UI.show_progress();
    $('filtered_report').update(new Element('p').update('Please wait while we retrieve your results.'))
    new Ajax.Request(event.element().href, {
      method:'get',
      onComplete:Brash.UI.hide_progress,
      onSuccess:Brash.Assorter.Responses.show_response.bind($('filtered_report'))
    });
    $$("a.current").invoke('removeClassName','current');
    event.element().addClassName('current');
  },
  show_response : function(t) {
    this.update(t.responseText);
    new Effect.Highlight(this);
  }.bind($('filtered_report'))
};

Brash.Account = {};
Brash.Account.Index = {
  init : function() {
    var handler;
    $('month').observe('change', Brash.Account.Index.filter);
  },
  filter : function(event) {
    var form = event.findElement('form');
    var regMonth = /(\d{4})-(\d{1,2})/;
    var matches = regMonth.exec(event.element().getValue());
    var year, month, path;
    if(matches && matches[1]) {
      path = "/account/"+matches[1];
      if(matches[2])
        path += "/"+matches[2];
    }
    else {
      path = "/account"
    }
    form = new Element('form', {action:path,method:'get'});
    $('content').insert({top:form});
    form.submit();
  }
};

Brash.Account.Settings = {
  init : function() {
    Brash.UI.focus_first($('update'));
    $('status').select('a.button').invoke('observe', 'click', Brash.Account.Settings.status_click);
    $('update').observe('submit', Brash.Account.Settings.submit);
    Brash.Account.Settings.show_description();
  },
  status_click: function(event) {
    event.stop();
    $('status').select('a.button').invoke('removeClassName', 'current');
    event.element().addClassName('current');
    $('user_status').value = event.findElement().name;
    Brash.Account.Settings.show_description();
  },
  show_description : function() {
    $$('p.status_description').invoke('hide');
    $('status_'+$F('user_status')).show();
  },
  submit : function(event) {
    if($F('user_status')=='closed' && !confirm('Are you sure you want to close this account? You will lose access to your account, all your ads, reporting statistics, and impression balances. Click OK to close your account and log off.')) {
      event.stop();
    }
  }
};


Brash.Account.Credits = {
  init : function() {
    $('charge').observe('submit', Brash.Account.Credits.do_submit);
  },
  do_submit: function(event) {
    var errors = [];
    if(!Brash.Util.validate_integer('credit_request_impressions')) {
      event.stop();
      alert('Please type how many ad views you would like credited to your account.');
      $('credit_request_impressions').select();
      return;
    }
  }
};

Brash.Results = {};
Brash.Results.Reports = {
  init : function() {
    Event.observe($('date-presets'),'change', function(event){
      $("start-date").value = event.target.getValue();
    });    
    Event.observe($('user-ads'),'change', function(event){
      window.location = event.target.getValue();
    });
  }
};

Brash.Ads = {}
Brash.Ads.Index = {
  init : function() {
    var self = Brash.Ads.Index;
    $$('#filter-states input[type=checkbox]').each(function(checkbox){
      checkbox.observe('change', function(){
        window.location.search = "?"+$('filter-states').serialize();
      });
    });
  }
}

Brash.Ads.Edit = {
  init : function() {
    Brash.Assorter.Settings.init();
    $$("div.toggable-select").each(function(div){
      div.down('span.select-toggle a').observe('click', function(e){
        e.stop();
        div.addClassName('show-select');
        div.down('select').writeAttribute('disabled',false);
      });
    });
  }
}

Brash.Page = {
  init : function() {
    $$('form.validated').each(function(form) {
      new Brash.Form(form);
    });
  }
};

Brash.Form = Class.create({
  regEmail : /\b[\w.%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i,
  regNonblank : /\S+/,
  initialize : function(form) {
    form.__brashValidator = this;
    form.observe('submit', this.validate.bindAsEventListener(this));
  },
  setError : function(input, errorMessage) {
    input.addClassName('error');
    input.insert({after:new Element('p',{className:'error'}).update(errorMessage)});
  },
  validate : function(event) {
    var inputs;
    var validated = true;
    var self = this;
    
    // Clear out existing errors
    event.element().select('input.validate.error').invoke('removeClassName','error');
    event.element().select('p.error').invoke('remove');
    
    // Validate emails
    event.element().select('input.validate.email').each(function(input) {
      if(!self.regEmail.test(input.getValue())) {
        validated = false;
        self.setError(input, 'A valid email address is required.');
      }
    });
    
    // Validate nonblanks
    event.element().select('input.validate.nonblank').each(function(input) {
      if(!self.regNonblank.test(input.getValue())) {
        validated = false;
        self.setError(input, 'This entry is required.');
      }
    });
    if(validated===false) {
      event.stop();
      event.element().select('input.validate.error').first().focus();
    }
  }
  
});

// Doing this to avoid some of the repetition that is present here
// Wrapping it in a self calling function avoids creating global 
// variables.
var PageLoader = (function(){
  var actions = {
    // assorters_index : Brash.Assorter.Index.init,
    assorters_compose : Brash.Assorter.Composer.init,
    ads_edit : Brash.Ads.Edit.init,
    ads_update : Brash.Ads.Edit.init,
    ads_index : Brash.Ads.Index.init, 
    account_index : Brash.Account.Index.init,
    account_settings : Brash.Account.Settings.init,
    account_update : Brash.Account.Settings.init,
    pages_show : Brash.Page.init
  };
  
  ['results_qctr_report', 'results_funnel_report', 'results_answer_report'].each(function(action){
    actions[action] = Brash.Results.Reports.init;
  });

  return Class.create(actions);
})();
  
var page_loaders = new PageLoader;


