// vim:syntax=javascript

// basic collision detection and display management for all sprite thingies

class Actor
{
    // the order of sprite names in the name array
    static var DIR_UP : Number = 0;
    static var DIR_LEFT : Number = 1;
    static var DIR_DOWN : Number = 2;
    static var DIR_RIGHT : Number = 3;

    static var DIR_POINTS : Array = [
        new Point(0,-1),
        new Point(-1,0),
        new Point(0,1),
        new Point(1,0)];

    static var DIR_OPPOSITE : Array = [
        DIR_DOWN,   // opposite of up
        DIR_RIGHT,  // opposite of left
        DIR_UP,     // opposite of down
        DIR_LEFT];  // opposite of right

    static var DIR_CLOCKWISE : Array = [
        DIR_RIGHT,  // clockwise from up
        DIR_UP,     // clockwise from left
        DIR_LEFT,   // clockwise from down
        DIR_DOWN];  // clockwise from right

    static var DIR_COUNTERCLOCKWISE : Array = [
        DIR_LEFT,   // cc from up
        DIR_DOWN,   // cc from left
        DIR_RIGHT,  // cc from down
        DIR_UP];    // cc from right

    private var _x : Number;
    private var _y : Number;
    private var _size : Number;
    private var _name_arr : Array;
    private var _dir : Number;
    private var _depth : Number;
    private var _parent_mc : LevelClip;
    private var _mc_name : String;
    private var _alive : Boolean;
    private var _onPress : Function;

    var onDeath : Function;

    function get x() : Number {return _x;}
    function get y() : Number {return _y;}
    function get size() : Number {return _size;}
    function get dir() : Number {return _dir;}
    function get dir_point() : Point {
        return DIR_POINTS[_dir];
    }
    function get alive() : Boolean {return _alive;}
    function get_parent_mc() : LevelClip {return _parent_mc;}
    function set_onPress(f : Function) {
        _parent_mc[_mc_name].onPress = _onPress = f;
    }
    function setMask(mc : MovieClip) {
        _parent_mc[_mc_name].setMask(mc);
    }

    function Actor(parent_mc:LevelClip, name_arr:Array, px:Number, py:Number, initial_dir:Number, psize:Number) {
        _parent_mc = parent_mc;
        _name_arr = name_arr;
        _depth = _parent_mc.getNextHighestDepth();
        _mc_name = "actor_"+_depth+"_mc";
        _x = px;
        _y = py;
        _size = psize;
        _alive = true;
        onDeath = null;
        setDirection(initial_dir);
    }

    static function vectorToDir(vx : Number, vy : Number) : Number {
        if (vy < 0) {
            return DIR_UP;
        }
        if (vx < 0) {
            return DIR_LEFT;
        }
        if (vy > 0) {
            return DIR_DOWN;
        }
        return DIR_RIGHT;
    }

    static function vectorToMajorDir(vx : Number, vy : Number) : Number {
        if (Math.abs(vx) > Math.abs(vy)) {
            if (vx < 0) {
                return DIR_LEFT;
            } else {
                return DIR_RIGHT;
            }
         } else {
             if (vy < 0) {
                 return DIR_UP;
             } else {
                 return DIR_DOWN;
             }
         }
    }

    // responsible for all attaches
    function setDirection(dir : Number) {
        _dir = dir;
        _parent_mc.attachMovie(_name_arr[_dir], _mc_name, _depth,
            {_x:_x,_y:_y,_width:_size,_height:_size,onPress:_onPress});
    }

    function setImages(names : Array, dir : Number) {
        _name_arr = names;
        setDirection(dir);
    }

    function canMoveTo(px : Number, py : Number) : Boolean {
        return !_parent_mc.checkPixelCollision(px, py, _size, _size);
    }

    function moveTo(px : Number, py : Number, pdir : Number) {
        _x = px;
        _y = py;
        if (pdir != _dir) {
            setDirection(pdir);
        } else {
            _parent_mc[_mc_name]._x = _x;
            _parent_mc[_mc_name]._y = _y;
        }
    }

    function doFrame() {
    }

    function killsGuy() : Boolean {
        return false;
    }

    function isGuy() : Boolean {
        return false;
    }

    function canBeKilled() : Boolean {
        return false;
    }

    function setDead() {
        _alive = false;
    }

    static function isRectangleWithinRadius(cx : Number, cy : Number,
        minx : Number, miny : Number, width : Number, height : Number,
        pr : Number) : Boolean {

            var dx1 = minx - cx;
            var dy1 = miny - cy;
            var dx2 = minx + width - 1 - cx;
            var dy2 = miny + height - 1 - cy;

        //trace("isRectangleWithinRadius("+cx+","+cy+","+mindx+","+mindy+","+maxdx+","+maxdy+","+pr+")");

        // Manhattan distance to find nearest corner

        var dist_coords = [
            [dx1, dy1],
            [dx2, dy1],
            [dx1, dy2],
            [dx2, dy2]];
        var best_x = dist_coords[0][0];
        var best_y = dist_coords[0][1];
        var best_dist = Math.abs(best_x)+Math.abs(best_y);

        for (var i = 1; i < dist_coords.length; i++) {
            var dist = Math.abs(dist_coords[i][0])+Math.abs(dist_coords[i][1]);
            if (dist < best_dist) {
                best_dist = dist;
                best_x = dist_coords[i][0];
                best_y = dist_coords[i][1];
            }
        }

        if ((best_x*best_x + best_y*best_y) < pr*pr) {
            return true;
        } else {
            return false;
        }
    }

    function isWithinRadius(px : Number, py : Number, pr : Number) : Boolean {
        return isRectangleWithinRadius(px, py, _x, _y, _size, _size, pr);
    }

    function remove() {
        _parent_mc[_mc_name].removeMovieClip();
    }
}
