/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/* Retrieve an asset attached to the slot of type type.
 * If nothing is attached to the slot - returns 0 */
function getAsset( type )
{
    var id = $("#result input[name="+type+"]").attr("value");
    if( !id )
        return 0;

    return $("#"+id);
}

/* A shortcut to get an ID of the asset. */
function getAssetId( asset )
{
    var id = $(asset).attr('id');
    if( !id )
        alert("No id!");

    return id;
}

/* Attach an asset to the slot of type type.
 * Pass null value as an asset, to clear the slot
 *
 * Currently supported types - utensils, hat, eyes, lips, scarf, and dress*/
function  setAsset( type, asset )
{
    var field = $("#result > input[name="+type+"]");
    if( !asset ) // Reset
        field.attr("value", "" );
    else
    {
        field.attr("value", asset.attr("id") );
    }
}

/* Reset all the assets to their starting position.*/
function resetAssets()
{
    $("#result > input[type=hidden]").each(function()
    {
        var type = $(this).attr("name");
        var asset = getAsset( type );   // The name is actually an asset ID
        if(asset) returnAsset( asset ); // If we have an asset in this slot - return it back to the gods
        setAsset( type, "" );           // Clear!
    });
}

/* Initialize assets and move them to initial position (palette)*/
function initializeAssets( )
{
    for(var key in assetDefs)
    {
        initializeAsset( key );
    }
}

function createAsset( key )
{
    if( !key )
        return "";
    
    var newElem = "<div id='" + key + "' class='asset " + assetDefs[key].type + "' style='z-index:" +
    assetDefs[key].zindex + "'>\
       <img src='assets/" + assetDefs[key].image.filename + "' alt=''";

	if( assetDefs[key].image.w && assetDefs[key].image.h )
		newElem += " width='" + assetDefs[key].image.w + "' height='" + assetDefs[key].image.h + "'";

	newElem += "></img></div>";

    return $(newElem);
}

function initializeAsset( key )
{
    var a = createAsset(key);
        
    // Get the position
    var x = assetDefs[key].pos.x;
    var y = assetDefs[key].pos.y;

    $("#assets-palette").append( a );
    //$("#assets-palette").css("position", "relative");

    $( a ).css("position", "absolute");
    $( a ).css({
        "left"  : x,
        "top"   : y
    });

    return a;
}

/* Retrieves a base utensil (attached to the slot)
 * See also: getAsset()*/
function getBase()
{
    return getAsset("utensils");
}

/* */
function resetDressingArea()
{
    resetAssets();


    $('#dressing-area').droppable({
        drop: function(event, ui)
        {
            var snapPoint = getSnapPoint( ui.draggable );
            dropAsset( ui.draggable, snapPoint, $(this), ui );
        }
    });

    $( "#dressing-area" ).droppable( "option", "accept", '.utensils' );
}

/* This function resets the base utensil (and thus all the assets attached) */
function resetBase()
{
    var base = getAsset("utensils");
    if(!base)
        return;

    returnAsset( base );
    resetDressingArea();
    $("#dressing-area").droppable("option", "accept", ".utensils");
}

/* Set a base asset
 * base: the asset itself
 * snapPoint : a point to snap to
 * container: the container element - actually it will never
 * become a true container, but it's position will be used to place the
 * assets*/
function setBase( base, snapPoint, container )
{
    setAsset("utensils", base );

    $(base).css('position', 'absolute');

    $(base).animate({'top' : $(container).position().top  + snapPoint.py ,
                     'left': $(container).position().left + snapPoint.px }, 300, 'swing');
                 
    // Now that we have the base utensil, we can accept other assets
    $("#dressing-area").droppable("option", "accept", ".asset");
}

/* Get the type of the passed in asset.
 * Invalid asset will result in this function returning undefined value*/
function getAssetType(asset)
{
    if( $(asset).hasClass('dress') )        {
        return "dress";
    }
    else if( $(asset).hasClass('lips') )    {
        return "lips";
    }
    else if( $(asset).hasClass('eyes') )    {
        return "eyes";
    }
    else if( $(asset).hasClass('hat') )     {
        return "hat";
    }
    else if( $(asset).hasClass('scarf') )   {
        return "scarf";
    }
    else if( $(asset).hasClass('utensils') ) {
        return "utensils";
    }
    else return undefined;
}

/* Return an asset to it's initial position*/
function returnAsset(asset)
{
    var type = getAssetType(asset);

    if ( type == undefined )
        alert ("Wrong asset type " + type );

    // Get the return position
    var x = assetDefs[$(asset).attr("id")].pos.x;
    var y = assetDefs[$(asset).attr("id")].pos.y;

    $(asset).animate({left: x, top: y}, 300, 'swing' );

    // Reset the slot
    setAsset(type, "");

}

/* Performs all the preparations to be able to drop the asset, such
 * as determining it's type, finding a suitable snap-to point, etc.*/
function dropAsset(asset, snapPoint, container)
{
    // utensils receive special treatment
    var type = getAssetType( asset );
    var isBase = ( type == "utensils" );
    if( isBase )
    {
        resetBase();
        setBase( asset, snapPoint, container );
        return;
    }

    var a = getAsset(type);
    if( !isBase && a )
    {
        if(a)
            returnAsset( a );
    }

    var base = getBase( );
    if( !base )
    {
        // Cannot drop assets - must drop utensil first
        return;
    }

    // Get the id of the asset - we need this to lookup the snapping information
    var id = getAssetId( asset );
    var assetSnap = assetDefs[id].snapPoint;

    // Since assets are positioned relative to their starting div, it takes a couple
    // of tricks to determine the position
    var top  =  ( $(base).position().top  - assetSnap.py ) + snapPoint.py ;
    var left =  ( $(base).position().left - assetSnap.px ) + snapPoint.px ;

    $(asset).css('position', 'absolute');

    $(asset).animate({'top': top, 'left': left}, 300, 'swing');
    $("#result > input[name=" + type + "]").attr("val", asset);
    setAsset( type, asset );
}

/* This is a utility function that retrieves a matching snap point for the given asset
 * and base*/
function getSnapOffset( assetType, baseId )
{
    var snapPoint = 0;

    if( assetType == "utensils" )
    {
        snapPoint = {
            "px" : 0 ,
            "py" : 0
        }

        return snapPoint;
    }
    
    switch( assetType )
    {
        case "dress":
            snapPoint = assetDefs[baseId].assetSnapPoints.dress;
            break;
        case "hat":
            snapPoint = assetDefs[baseId].assetSnapPoints.hat;
            break;
        case "lips":
            snapPoint = assetDefs[baseId].assetSnapPoints.lips;
            break;
        case "eyes":
            snapPoint = assetDefs[baseId].assetSnapPoints.eyes;
            break;
        case "scarf":
            snapPoint = assetDefs[baseId].assetSnapPoints.scarf;
            break;
        case "utensils":
            snapPoint = assetDefs[baseId].snapPoint;
            break;
    }
    
    return snapPoint;
}

function _getSnapPoint( assetId )
{
    var assetSnap = assetDefs[assetId].snapPoint;
    return assetSnap;
}

function getAssetCorner( assetType, assetId, baseId, relativeTo )
{
    var so = getSnapOffset( assetType, baseId );
    var sp = _getSnapPoint( assetId );
    var rt = $(relativeTo).position();

    var corner = { "px" : so.px - sp.px + rt.left, "py" : so.py - sp.py + rt.top };

    return corner;
}

/* Get a snap-to point for the asset.*/
function getSnapPoint( asset )
{
    var snapPoint = 0;

    var base = getBase();

    var assetType = getAssetType( asset );

    if( assetType == "utensils" )
    {
        // Special case - we want the base utensil centered
        // in the dressing area
        var w  = $(asset).width();
        var h  = $(asset).height();

        var dw = $("#dressing-area").width();
        var dh = $("#dressing-area").height();

        snapPoint = {
            "px" : Math.ceil((dw / 2) - (w / 2)) ,
            "py" : Math.ceil((dh / 2) - (h / 2)),
            "currentAsset" : 0
        }
        return snapPoint;
    }

    var baseId = getAssetId( base );


    switch( assetType )
    {
        case "dress":
            snapPoint = assetDefs[baseId].assetSnapPoints.dress;
            break;
        case "hat":
            snapPoint = assetDefs[baseId].assetSnapPoints.hat;
            break;
        case "lips":
            snapPoint = assetDefs[baseId].assetSnapPoints.lips;
            break;
        case "eyes":
            snapPoint = assetDefs[baseId].assetSnapPoints.eyes;
            break;
        case "scarf":
            snapPoint = assetDefs[baseId].assetSnapPoints.scarf;
            break;
        case "utensils":
            snapPoint = assetDefs[baseId].snapPoint;
            break;
    }

    return snapPoint;
}

function positionAsset( asset, corner )
{
    //var relativeOffset = $(relativeTo).position();
    $(asset).css('position', 'absolute');
    $(asset).css({'left': corner.px, 'top': corner.py});
}

function assemblePuppet()
{
    var baseId = 0;
    var base = 0;

    $("#result div input[name=utensils]").each(function()
    {
        baseId    = $(this).attr("value");
        var asset = createAsset( baseId );

        $("#puppet-frame > div").append(asset);

        // Special case - we want the base utensil centered
        // in the dressing area
        var w  = $(asset).find('img').width();
        var h  = $(asset).find('img').height();

        var dw = $("#puppet-frame").width();
        var dh = $("#puppet-frame").height();

        var coord = {
            "px" : Math.ceil((dw / 2) - (w / 2)) ,
            "py" : Math.ceil((dh / 2) - (h / 2)) };

        $(asset).css({
            'position' : 'absolute',
            'left'     : coord.px,
            'top'      : coord.py
        });

        base = asset;
    });

    $("#result div input[type=hidden]").each(function()
    {
        var name  = $(this).attr("name");
        var assetId  = $(this).attr("value");
        if(name == "utensils" || !assetId )
            return; // Skip
        
        
        var asset = createAsset( assetId );
        $("#puppet-frame > div").eq(0).append(asset);

        var crn = getAssetCorner( name, assetId, baseId, $(base) );

        positionAsset( asset, {"px" : crn.px, "py" : crn.py } );
    });
    
}

