if( typeof( api ) == "undefined" ){ api = {}; api.ns = "api"; }

/**
 * User model
 */

api.User =  function( user_dictionary ){
  user_dictionary = lu.default_to(user_dictionary, {});
  if( !user_dictionary.mugshot_url && user_dictionary.mugshot_thumb_url ){
    user_dictionary.mugshot_url = user_dictionary['mugshot_thumb_url'];
  }

  lu.absorb(this, user_dictionary, api.User.legal_attributes);

  if( !this.display_name || this.display_name.length === 0 ){
    this.display_name = 'anonymous';
  }

};

api.User.legal_attributes = [
    'display_name',
    'tags',
    'user_id',
    'puid',
    'link',
    'fan_permission',
    'mugshot_url'
  ];

api.User.create = function(dict){
  return new api.User(dict);
};

api.User.create_many = function( user_dictionaries ){
  var users = [];
  $.each(user_dictionaries, function(which_user_dictionary, each_user_dictionary){
    users.push(new api.User(each_user_dictionary));
  });
  return users;
};


////////////////////////////////////////
//
// instance members

api.User.prototype = {

  click_name : function(){
	var images = "";
	if (this.tags) {
	    for (var i=0; i<this.tags.length; i++) {
		images += '<img class="profile_mug" src="'+this.tags[i]+'"/>';
	    }
	}
	if (this.link) {
	    return '<span class="click_name"><a href="'+this.link+'">'+images+'</a> <a href="'+this.link+'">'+this.display_name+'</a></span>';
	} else {
	    return '<span class="click_name">'+images+' '+this.display_name+'</span>';
	}
  },

  fetch_contacts : function( on_success ){
    if( this.puid !== AppBase.user.puid ){ throw {name:'bad_contact_fetch',message:'Attempted to fetch contacts of a non-visitor user'}; }
    var that = this;
    if( that.contacts ){ on_success(that.contacts); }
    api.User.fetch_contacts(function( result ){
      that.contacts = api.User.create_many(result.address_book);
      on_success(that.contacts);
    });
  },

  scrape : function( params ){
    if( this.puid !== AppBase.user.puid ){ throw {name:'bad_scrape',message:'Attempted to scrape email of a non-visitor user'}; }
    AppBase.post(
    '/contacts',
      {
        'xaction' : 'scrape',
        'inviter_email' : params.name,
        'inviter_provider' : params.provider,
        'inviter_password' : params.password
      },
      function(response){ //Success function
        //todo: add contacts to that.contacts
        this.contacts = this.contacts + response.new_contacts;
        params.callback(response);
      },
      function(response){ //Failure function
        response = eval("("+response+")");
        response.error = response.type;
        delete response.type; //todo: this is to support the old inviter - unify all inviters and nix this
        params.callback(response);
      }
    );
  },
  invite_to_group : function( params ){
    if( this.puid !== AppBase.user.puid ){ throw {name:'bad_scrape',message:'Attempted to invite using non-visitor user'}; }
    AppBase.post(
    '/contacts',
      {
        'xaction' : 'invite_to_group',
        'puids' : params.puids,
        'message' : params.message,
        'focal_group_puid' : params.group_puid
      },
      function(response){ //Success function
        //todo: add contacts to that.contacts
        if( params.callback ){ params.callback(response); }
      },
      function(response){ //Failure function
        response = eval("("+response+")");
        response.error = response.type;
        delete response.type; //todo: this is to support the old inviter - unify all inviters and nix this
        if( params.callback ){ params.callback(response); }
      }
    );
  }
};

api.User.prototype.get_mugshot_url = function(options){
  if( this.mugshot_url ){
    return AppBase.redeco(this.mugshot_url, {'height':options.height, 'width':options.width});
  }else{
    // todo: help me! I can't be redecoed
    return Serdes.make_static_url('/images/no_mugshot.jpg');
  }
};

/* Creates a dom node displaying the user's mugshot.
 * @options can include
 *   image_height: pixel height of image
 *   image_width: pixel width of image
 *   framed: if truthy, the mugshot will be centered within a frame (note - non-truthy currently unsupported)
 *   frame_height: fixed pixel height of frame
 *   frame_width: fixed pixel width of frame
 *   onclick: a callback to be invoked when the mugshot is clicked
 *   caption: a string to be placed underneath the mugshot.  If set to true, the display_name will be the caption
 */
api.User.prototype.render_mugshot = function(options){
  options = lu.defaulted(options, {});
  options = lu.defaults(options, {
			  'image_width' : 100,
			  'image_height' : 100,
			  'frame_width' : 110,
			  'frame_height' : 110
			});
  var image = IMG({'src' : this.get_mugshot_url({height:options.image_height, width:options.image_width})});
  var result = image;
  if( options.frame ){
    var framed = TABLE({'class':'centering_frame framed_mugshot'},TBODY({},TR({},TD({'align':'center'},  result  ))));
    if( options.frame_height ){ $(framed).css({'height' : options.frame_height+'px'}); }
    if( options.frame_width  ){ $(framed).css({'width'  : options.frame_width +'px'}); }
    result = framed;
  }
  if( options.caption !== undefined ){
    if( options.caption === true ){ options.caption = this.display_name; }
    var captioned = DIV({'class':'mugshot_caption'}, result, options.caption );
    result = captioned;
  }
  if( options.onclick ){
    $(result).css({'cursor':'pointer'});
    $(result).click(options.onclick);
  }
  return result;
};

////////////////////////////////////////
//
// class members

api.User.users = {};

api.User.to_autoselect_array = function( users ){
  var autoselect_array = [];
  $.each(users, function(which, user){
    autoselect_array.push([user.display_name, '', user.puid]);
  });
  return autoselect_array;
};

api.User.fetch_contacts = function(on_success){
	AppBase.post(
		'/contacts',
		{'xaction':'fetch_address_book'}, // todo: make this call something better than the antiquated 'fetch addres book'
		on_success
	);
};

// options can be:
//   fan_permission
//   puid: puid of user to fan.  only one of fan_permission or puid is required
//   on_fan: callback that executes after success is returned from call to server
api.User.fan = function( options ){
  options = lu.defaulted(options, {});
  var parameters =     {
    'xaction':'fan_users'
  };
  if( options.fan_permission ){
    parameters.fan_permission = options.fan_permission;
  }else if( options.puid ){
    parameters.puid = options.puid;
  }else if( options.users ){
    var puids = [];
    $.each(options.users, function(which, user){
      puids.push(user.puid);
    });
    parameters.puids = puids;
  }
  if( options.ref_overrride ){ parameters.ref_override = options.ref_override; }
  AppBase.post(
    '/profile',
    parameters,
    function( response ){ api.User._on_fan( response, {'success_callback' : options.on_fan, 'failure_callback':options.on_fan_failure} ); }
  );
  return false;
};

api.User._on_fan = function( response, options ){
  // options can include
  //   success_callback
  //   failure_callback
  options = lu.defaulted(options, {});
  options.failure_callback = lu.defaulted(options.failure_callback, function(){ alert(
    translate('blocked_fan_deny'));
  });
  if( response && response['error'] ){
    if( options.failure_callback ){
      options.failure_callback(response);
    }
  }else{
    if( options.success_callback ){
      options.success_callback(response);
    }
  }
};

api.User.templates = function(){};

api.User.templates.user_list = function(users, options){
  options = lu.default_to(options, {});

  options.element_template = lu.default_to(options.element_template, function( user ){
    return DIV({},user.display_name);
  });

  options.list_template = lu.default_to(options.list_template, function( elements ){
    var list = UL({});
    $.each(elements, function(which_element, each_element){
      list.appendChild(LI({},each_element));
    });
    return list;
  });

  return bu.list(users, {
    'element_template':options.element_template,
    'list_template':options.list_template
  });
};

/*
 * options may include
 *   on_select: an event that occurrs when an item changes selection state
 *   element_template: a function that recieves an object representing a user and transforms it into a dom element
 *   list_template: a function that accepts a list of elements and returns a dom element containing them all
*/
api.User.templates.user_selector = function(users, options){
  options = lu.default_to(options, {});
  options.on_select = lu.default_to(options.on_select, function(selected, element, user){
    $(element).css('background-color', (selected?'#DDD':''));
    $(element)[(selected?'add':'remove')+'Class']('selected_user');
    user.selected = selected;
  });

  options.element_template = lu.default_to(options.element_template, function(user){
    return DIV({'id':'user_selector'}, user.display_name);
  });

  options.list_template = lu.default_to(options.list_template, function(elements){
    var list = UL({});
    $.each(elements, function(which_element, each_element){
      list.appendChild(LI({},each_element));
    });
    return list;
  });
  var selector = bu.selector(users, {
    'on_select':options.on_select,
    'element_template':options.element_template,
    'list_template':options.list_template,
    'empty_template':options.empty_template,
    'preselected' : options.preselected
  });
  return selector;
};


api.User.templates.render_channel_list = function( user_id, width, height, target_id ){

  if( typeof( target_id ) == "undefined" ){ target_id = "ticker_holder"; }

  var swf = "http://"+api.widget_domain+"/widgets/channelViewer.swf";
  var fo = new FlashObject(swf ,target_id+"_embed", width, height, '8', '');

  //fo.addParam("user", user_id);
  //fo.addParam("site", api.widget_domain);
  //fo.addParam("cv_width", width);
  //fo.addParam("cv_height", height);
  //fo.addParam("cv_orientation", "vertical");
  var flashVarStr = "user="+user_id+"&site="+api.widget_domain+"&cv_width="+width+"&cv_height="+height+"&cv_orientation=vertical";
  fo.addParam("FlashVars", flashVarStr);
  fo.write(target_id);
};

if( AppBase.user ){
  AppBase.user = new api.User(AppBase.user);
}

