// do we know about their rights?
function know_rights() {
  return !(!rights);
}

// do they have the given right?
function has_right(right, actor_id) {
  if (!know_rights()) {
    return false;
  }
  return has_right_in_set(right, actor_id, rights);
}
function has_right_in_set(right, actor_id, rights) {
  // don't know about this type of right
  if (!rights.rights[right]) {
    return false;
  }
  
  if (actor_id) {
    // a specific actor has it
    return rights.rights[right].member(actor_id);
  } else {
    // any of their actors have it
    return rights.rights[right].size();
  }
}

// do they have the given role?
function has_role(role, actor_id) {
  if (!know_rights()) {
    return false;
  }
  return has_role_in_set(role, actor_id, rights);
}
function has_role_in_set(role, actor_id, rights) {
  if (!rights.roles[role]) {
    return false;
  }
  
  if (actor_id) {
    // a specific actor has it
    return rights.roles[role].member(actor_id);
  } else {
    // any of their actors have it
    return rights.roles[role].size();
  }
}

// the given actor details
function getActor(actor_id) {
  return can_act_as[actor_id];
}

// an array of all the actors they can be
function all_actors() {
  var actors = Array();
  $H(can_act_as).each(function(actor){
    actors.push(actor[0]);
  });
  return actors;
}



function some_actors_match(options) {
  // either use the context rights
  var rights_set = rights;
  // ...or the ones given to us
  if (options.rights_set)
    rights_set = options.rights_set;

  // any of the actors mathc the rule?
  return (matching_actors(options.rules, rights_set).length > 0);
}

function all_actors_match(options) {
  // either use the context rights
  var rights_set = rights;
  // ...or the ones given to us
  if (options.rights_set)
    rights_set = options.rights_set;

  // find all the actors that match the rules
  var actors = matching_actors(options.rules, rights_set);

  // is it every actor?
  return (actors.length == all_actors().length);
}

function actor_picker(callback, options) {
  // either use the context rights
  var rights_set = rights;
  // ...or the ones given to us
  if (options.rights_set)
    rights_set = options.rights_set;

  // find all the actors that match the rules
  var actors = matching_actors(options.rules, rights_set);
  if (actors.length == 0) {
    callback(null);
    return true;
  }

  // if this user can only be one actor than there's nothing to do
  var possible_actors = all_actors();
  if (possible_actors.length == 1) {
    callback(possible_actors[0]);
    return true;
  }

  // get / build the actor picker
  var actor_list = actor_set();

  // get rid of any old pickers
  $$('.actor-picker-form').each(function(frm){ frm.remove(); });

  // create the picker form shell
  var picker = new Element('form', { className:'actor-picker-form' });
  picker.insert(actor_list);
  picker.insert(new Element('input', { className:'actor-picker-done-btn', type:'image', name:'done', src:'/images/buttons/medium/srt_select.gif' }));

  // attach the event so we know what to do when done
  Event.observe(picker, 'submit', function(e) { Event.stop(e); actor_selected(callback); });

  // display in the popover
  pop_over(picker);
  
  // only show the ones they can select
  actor_list.select('.actor').each(function(elm){
    actor_deactivate(elm);
  });
  actors.each(function(actor_id){
    actor_activate($('full-actor-select-' + actor_id.toString()));
  });
  // pre select the given one (if given)
  if (options.current_actor_id)
    $('full-actor-select-' + options.current_actor_id.toString()).down('input').checked = true;

}

function actor_selected(callback) {
  pop_over_close();

  // find the new actor_id
  var actor_id = null;
  $$('#full-actor-set .possible-actor').each(function(elm){
    if (elm.checked) {
      actor_id = elm.value;
    }
  });

  callback(actor_id);
}

function actor_deactivate(actor){
  actor.down('.actor-inner').setOpacity(.2);
  actor.down('input').disabled = true;
}

function actor_activate(actor){
  actor.down('.actor-inner').setOpacity(1);
  actor.down('input').disabled = false;
}

function actor_set(){
  // is there an html actor set floating around somewhere?
  var actor_set = $('full-actor-set');
  if (actor_set) {
    return actor_set;
  }

  // need to build a new one
  var actor_set = new Element('div', { id:'full-actor-set'});
  actor_set.insert(new Element('h4').update('Select Your Identity'));

  // select your identity

  all_actors().each(function(actor_id){
    var a = getActor(actor_id);
    
    // build a representation of the actor
    var actor_rep = new Element('div', { className:'actor', id:'full-actor-select-' + actor_id.toString() });
    var actor_in = new Element('div', { className:'actor-inner' });
    actor_rep.insert(actor_in);
    actor_in.insert(new Element('img', { src:a.tiny_thumb }));
    actor_in.insert(new Element('div', { className:'detail' }).insert(new Element('h4').update(a.name)));
    actor_in.insert(new Element('input', { className:'possible-actor', type:'radio', name:'actor_id', value:actor_id }));
    actor_in.insert(new Element('div', { className:'clear' }));
    Event.observe(actor_in, 'click', function(e){ var inp = actor_in.down('input'); if (!inp.disabled) inp.checked = true; });
    actor_set.insert(actor_rep);
  });

  return actor_set;
}

// find all of their actors that match the given rules
function matching_actors(rules, rights_set) {
  // make sure we have a rule set
  if (!rules) { rules = {}; }
  // start with all actors
  var actors = all_actors();
  // filter by rights
  if (rules.right) {
    $w(rules.right).each(function(right){
      actors = actor_match(actors, right, function(actor_id, right){ return has_right_in_set(right, actor_id, rights_set); } );
    });
  }
  // filter by roles
  if (rules.role) {
    $w(rules.role).each(function(role){
      actors = actor_match(actors, role, function(actor_id, role){ return has_role_in_set(role, actor_id, rights_set); } );
    });
  }
  // filter by actor_type
  if (rules.actor_type) {;
    $w(rules.actor_type).each(function(actor_type){
      actors = actor_match(actors, actor_type, function(actor_id, actor_type){ return getActor(actor_id).actor_type == actor_type; } );
    });
  }
  // done!
  return actors;
}

// filter the actors list to the ones that pass the test
function actor_match(actors, field, test_func) {
  var filtered_actors = Array();
  var negate = false;
  
  // doing a negation filter?
  if (field.charAt(0) == '!') {
    field = field.replace('!', '');
    negate = true;
  }

  // go filter!
  actors.each(
    function(actor_id){
      if (!negate != !test_func(actor_id, field)) {
        filtered_actors.push(actor_id);
      }
    }
  );
  // easy
  return filtered_actors;
}


