"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Head_1 = require("./Head");
var PlayerPart_1 = require("./PlayerPart");
var utils_1 = require("../utils");
var PlayerStat;
(function (PlayerStat) {
    PlayerStat[PlayerStat["RELEASE"] = 0] = "RELEASE";
    PlayerStat[PlayerStat["RISING"] = 1] = "RISING";
    PlayerStat[PlayerStat["FALL"] = 2] = "FALL";
})(PlayerStat || (PlayerStat = {}));
var debug = false;
var Player = (function (_super) {
    __extends(Player, _super);
    function Player() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.partMass = 0.1;
        _this.footMass = 0.1;
        _this.shouldersDistance = 50 / utils_1.getfactor();
        _this.speed = 30;
        _this.skin = '';
        _this.originPos = {};
        _this.safePos = 0;
        _this.onPostStep = function (e) {
            if (e === void 0) { e = null; }
            var side = _this.currentSide;
            var footHang = _this.foots[_this.currentSide];
            var footFall = _this.foots[_this.anotherSide];
            switch (_this.state) {
                case PlayerStat.FALL:
                    break;
                case PlayerStat.RISING:
                    var footOffset = footHang.position[0] - footFall.position[0];
                    var speed = _this.speed;
                    _this.upperLegs[side].angularVelocity = 10;
                    _this.upperLegs[side].velocity = [
                        footOffset < 0 ? speed - 10 : speed,
                        0
                    ];
                    _this.lowerLegs[side].velocity = [
                        footOffset < 0 ? speed - 10 : speed,
                        footOffset < 0 ? 3 : 2
                    ];
                    _this.head.velocity = [speed * 0.5, 20];
                    _this.dispatchEvent('move', {
                        pos: (_this.leftFoot.position[0] + _this.rightFoot.position[0]) / 2 * utils_1.getfactor(),
                        bodyPos: _this.body.position[0] * utils_1.getfactor(),
                    }, true);
                    if (footOffset > 50) {
                        _this.up();
                    }
                    break;
                case PlayerStat.RELEASE:
                    _this.head.velocity = [0, 30];
                    break;
            }
        };
        _this.onFootDown = function () {
            var pos = _this.foots[_this.currentSide].position[0] * utils_1.getfactor();
            var mileage = Math.max(_this.foots[0].position[0], _this.foots[1].position[0]) * utils_1.getfactor();
            _this.safePos = _this.foots[_this.currentSide].position[0];
            _this.dispatchEvent('foot_down', {
                mileage: mileage,
                pos: pos,
            }, true);
        };
        return _this;
    }
    Player.prototype.setup = function (options) {
        var collisionGroup = options.collisionGroup, collisionMask = options.collisionMask, world = options.world, ground = options.ground;
        this.world = world;
        world.on('postStep', this.onPostStep);
        var bodyPartShapes = [];
        var leftFootDisplay = this.createDisplay('foot');
        var lowerLeftLegDisplay = this.createDisplay('lower_left_leg');
        var upperLeftLegDisplay = this.createDisplay('upper_left_leg');
        var rightFootDisplay = this.createDisplay('foot');
        var lowerRightLegDisplay = this.createDisplay('lower_right_leg');
        var upperRightLegDisplay = this.createDisplay('upper_right_leg');
        var bodyDisplay = this.createDisplay('body', { x: 50, y: 0 });
        var headDisplay = new Head_1.Head();
        var upperLeftArmDisplay = this.createDisplay('upper_left_arm');
        var lowerLeftArmDisplay = this.createDisplay('lower_left_arm', { x: -20, y: 0 });
        var upperRightArmDisplay = this.createDisplay('upper_right_arm');
        var lowerRightArmDisplay = this.createDisplay('lower_right_arm', { x: -39, y: 0 });
        var leftFootShape = new p2.Box(leftFootDisplay.fSize);
        bodyPartShapes.push(leftFootShape);
        this.originPos['leftFoot'] = [
            -this.shouldersDistance / 2,
            leftFootDisplay.fHeight / 2
        ];
        var leftFoot = this.leftFoot = new p2.Body({
            allowSleep: false,
            mass: this.footMass,
            position: this.originPos['leftFoot'],
        });
        if (!debug)
            leftFoot.displays = [leftFootDisplay];
        leftFoot.addShape(leftFootShape);
        var lowerLeftLegShape = new p2.Box(lowerLeftLegDisplay.fSize);
        bodyPartShapes.push(lowerLeftLegShape);
        this.originPos['lowerLeftLeg'] = [
            -this.shouldersDistance / 2,
            leftFoot.position[1] + lowerLeftLegDisplay.fHeight / 2 + 5 / utils_1.getfactor()
        ];
        var lowerLeftLeg = this.lowerLeftLeg = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['lowerLeftLeg'],
        });
        if (!debug)
            lowerLeftLeg.displays = [lowerLeftLegDisplay];
        lowerLeftLeg.addShape(lowerLeftLegShape);
        var leftAnkleJoint = new p2.RevoluteConstraint(lowerLeftLeg, leftFoot, {
            localPivotA: [0, -lowerLeftLegDisplay.fHeight / 2 + 5 / utils_1.getfactor()],
            localPivotB: [-leftFootDisplay.fWidth / 2 + 18 / utils_1.getfactor(), 0],
        });
        leftAnkleJoint.setLimits(-Math.PI / 3, Math.PI / 3);
        var leftFootGroundCons = this.leftFootGroundCons = new p2.RevoluteConstraint(leftFoot, ground, {
            localPivotA: [0, -leftFootDisplay.fHeight / 2],
            localPivotB: [leftFoot.position[0], 0],
        });
        leftFootGroundCons.setLimits(0, 0);
        var upperLeftLegShape = new p2.Box(upperLeftLegDisplay.fSize);
        bodyPartShapes.push(upperLeftLegShape);
        this.originPos['upperLeftLeg'] = [
            -this.shouldersDistance / 2,
            lowerLeftLeg.position[1] + lowerLeftLegDisplay.fHeight / 2 + upperLeftLegDisplay.fHeight / 2 - 40 / utils_1.getfactor()
        ];
        var upperLeftLeg = this.upperLeftLeg = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['upperLeftLeg'],
        });
        if (!debug)
            upperLeftLeg.displays = [upperLeftLegDisplay];
        upperLeftLeg.addShape(upperLeftLegShape);
        var leftKneeJoint = new p2.RevoluteConstraint(upperLeftLeg, lowerLeftLeg, {
            localPivotA: [0, -upperLeftLegDisplay.fHeight / 2 + 20 / utils_1.getfactor()],
            localPivotB: [0, lowerLeftLegDisplay.fHeight / 2 - 20 / utils_1.getfactor()],
        });
        leftKneeJoint.setLimits(-Math.PI, 0);
        var rightFootShape = new p2.Box(rightFootDisplay.fSize);
        bodyPartShapes.push(rightFootShape);
        this.originPos['rightFoot'] = [
            this.shouldersDistance / 2,
            rightFootDisplay.fHeight / 2
        ];
        var rightFoot = this.rightFoot = new p2.Body({
            allowSleep: false,
            mass: this.footMass,
            position: this.originPos['rightFoot'],
        });
        if (!debug)
            rightFoot.displays = [rightFootDisplay];
        rightFoot.addShape(rightFootShape);
        var lowerRightLegShape = new p2.Box(lowerRightLegDisplay.fSize);
        bodyPartShapes.push(lowerRightLegShape);
        this.originPos['lowerRightLeg'] = [
            this.shouldersDistance / 2,
            rightFoot.position[1] + lowerRightLegDisplay.fHeight / 2 + 5 / utils_1.getfactor()
        ];
        var lowerRightLeg = this.lowerRightLeg = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['lowerRightLeg'],
        });
        if (!debug)
            lowerRightLeg.displays = [lowerRightLegDisplay];
        lowerRightLeg.addShape(lowerRightLegShape);
        var rightAnkleJoint = new p2.RevoluteConstraint(lowerRightLeg, rightFoot, {
            localPivotA: [0, -lowerRightLegDisplay.fHeight / 2 + 5 / utils_1.getfactor()],
            localPivotB: [-rightFootDisplay.fWidth / 2 + 18 / utils_1.getfactor(), 0],
        });
        rightAnkleJoint.setLimits(-Math.PI / 3, Math.PI / 3);
        var rightFootGroundCons = this.rightFootGroundCons = new p2.RevoluteConstraint(rightFoot, ground, {
            localPivotA: [0, -rightFootDisplay.fHeight / 2],
            localPivotB: [rightFoot.position[0], 0],
        });
        rightFootGroundCons.setLimits(0, 0);
        var upperRightLegShape = new p2.Box(upperRightLegDisplay.fSize);
        bodyPartShapes.push(upperRightLegShape);
        this.originPos['upperRightLeg'] = [
            this.shouldersDistance / 2,
            lowerRightLeg.position[1] + lowerRightLegDisplay.fHeight / 2 + upperRightLegDisplay.fHeight / 2 - 40 / utils_1.getfactor()
        ];
        var upperRightLeg = this.upperRightLeg = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['upperRightLeg'],
        });
        if (!debug)
            upperRightLeg.displays = [upperRightLegDisplay];
        upperRightLeg.addShape(upperRightLegShape);
        var rightKneeJoint = new p2.RevoluteConstraint(upperRightLeg, lowerRightLeg, {
            localPivotA: [0, -upperRightLegDisplay.fHeight / 2 + 20 / utils_1.getfactor()],
            localPivotB: [0, lowerRightLegDisplay.fHeight / 2 - 20 / utils_1.getfactor()],
        });
        rightKneeJoint.setLimits(-Math.PI, 0);
        var bodyWidth = 120 / utils_1.getfactor();
        var bodyHeight = 250 / utils_1.getfactor();
        var bodyShape = new p2.Box({ width: bodyWidth, height: bodyHeight });
        bodyPartShapes.push(bodyShape);
        this.originPos['body'] = [
            0,
            upperRightLeg.position[1] + upperRightLegDisplay.fHeight / 2 + bodyHeight / 2 - 60 / utils_1.getfactor()
        ];
        var body = this.body = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['body'],
        });
        if (!debug)
            body.displays = [bodyDisplay];
        body.addShape(bodyShape);
        var leftHipJoint = new p2.RevoluteConstraint(body, upperLeftLeg, {
            localPivotA: [-20 / utils_1.getfactor(), -bodyHeight / 2 + 30 / utils_1.getfactor()],
            localPivotB: [0, upperLeftLegDisplay.fHeight / 2 - 30 / utils_1.getfactor()],
        });
        leftHipJoint.setLimits(-Math.PI / 6 * 2, Math.PI / 6 * 2);
        var rightHipJoint = new p2.RevoluteConstraint(body, upperRightLeg, {
            localPivotA: [-20 / utils_1.getfactor(), -bodyHeight / 2 + 30 / utils_1.getfactor()],
            localPivotB: [0, upperRightLegDisplay.fHeight / 2 - 30 / utils_1.getfactor()],
        });
        rightHipJoint.setLimits(-Math.PI / 6 * 2, Math.PI / 6 * 2);
        var headShape = new p2.Circle({ radius: 85 / utils_1.getfactor() });
        bodyPartShapes.push(headShape);
        this.originPos['head'] = [
            0,
            body.position[1] + bodyHeight / 2 + 85 / utils_1.getfactor()
        ];
        var head = this.head = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['head'],
        });
        head.addShape(headShape);
        if (!debug)
            head.displays = [headDisplay];
        var headJoint = new p2.RevoluteConstraint(body, head, {
            localPivotA: [0, bodyHeight / 2 - 10 / utils_1.getfactor()],
            localPivotB: [0, (-85 + 10) / utils_1.getfactor()],
        });
        headJoint.setLimits(-Math.PI / 6 * 2, Math.PI / 6 * 2);
        var upperLeftArmShape = new p2.Box(upperLeftArmDisplay.fSize);
        bodyPartShapes.push(upperLeftArmShape);
        this.originPos['upperLeftArm'] = [
            -this.shouldersDistance / 2 - 10 / utils_1.getfactor(),
            body.position[1] + bodyHeight / 2 - upperLeftArmDisplay.fHeight / 2
        ];
        var upperLeftArm = this.upperLeftArm = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['upperLeftArm'],
        });
        if (!debug)
            upperLeftArm.displays = [upperLeftArmDisplay];
        upperLeftArm.addShape(upperLeftArmShape);
        var leftShoulderJoint = new p2.RevoluteConstraint(body, upperLeftArm, {
            localPivotA: [-this.shouldersDistance / 2 + 10 / utils_1.getfactor(), bodyHeight / 2],
            localPivotB: [0, upperLeftArmDisplay.fHeight / 2],
        });
        leftShoulderJoint.setLimits(-Math.PI / 2, 0);
        var width = 50 / utils_1.getfactor();
        var lowerLeftArmShape = new p2.Box({ width: width, height: lowerLeftArmDisplay.fHeight });
        bodyPartShapes.push(lowerLeftArmShape);
        this.originPos['lowerLeftArm'] = [
            -this.shouldersDistance / 2 - 10 / utils_1.getfactor() + 10 / utils_1.getfactor(),
            upperLeftArm.position[1] - upperLeftArmDisplay.fHeight / 2 - lowerLeftArmDisplay.fHeight / 2 + 20 / utils_1.getfactor()
        ];
        var lowerLeftArm = this.lowerLeftArm = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['lowerLeftArm'],
        });
        if (!debug)
            lowerLeftArm.displays = [lowerLeftArmDisplay];
        lowerLeftArm.addShape(lowerLeftArmShape);
        var leftElbowJoint = new p2.RevoluteConstraint(upperLeftArm, lowerLeftArm, {
            localPivotA: [0, -upperLeftArmDisplay.fHeight / 2 + 10 / utils_1.getfactor()],
            localPivotB: [-10 / utils_1.getfactor(), lowerLeftLegDisplay.fHeight / 2 - 10 / utils_1.getfactor()],
        });
        leftElbowJoint.setLimits(0, Math.PI * 2 / 3);
        var upperRightArmShape = new p2.Box(upperRightArmDisplay.fSize);
        bodyPartShapes.push(upperRightArmShape);
        this.originPos['upperRightArm'] = [
            this.shouldersDistance / 2,
            body.position[1] + bodyHeight / 2 - upperRightArmDisplay.fHeight / 2
        ];
        var upperRightArm = this.upperRightArm = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['upperRightArm'],
        });
        if (!debug)
            upperRightArm.displays = [upperRightArmDisplay];
        upperRightArm.addShape(upperRightArmShape);
        var rightShoulderJoint = new p2.RevoluteConstraint(body, upperRightArm, {
            localPivotA: [this.shouldersDistance / 2 + 10 / utils_1.getfactor(), bodyHeight / 2],
            localPivotB: [0, upperRightArmDisplay.fHeight / 2],
        });
        rightShoulderJoint.setLimits(-Math.PI / 2, 0);
        var width = 30 / utils_1.getfactor();
        var lowerRightArmShape = new p2.Box({ width: width, height: lowerRightArmDisplay.fHeight });
        bodyPartShapes.push(lowerRightArmShape);
        this.originPos['lowerRightArm'] = [
            this.shouldersDistance / 2,
            upperRightArm.position[1] - upperRightArmDisplay.fHeight / 2 - lowerRightArmDisplay.fHeight / 2 + 40 / utils_1.getfactor()
        ];
        var lowerRightArm = this.lowerRightArm = new p2.Body({
            allowSleep: false,
            mass: this.partMass,
            position: this.originPos['lowerRightArm'],
        });
        if (!debug)
            lowerRightArm.displays = [lowerRightArmDisplay];
        lowerRightArm.addShape(lowerRightArmShape);
        var rightElbowJoint = new p2.RevoluteConstraint(upperRightArm, lowerRightArm, {
            localPivotA: [0, -upperRightArmDisplay.fHeight / 2 + 20 / utils_1.getfactor()],
            localPivotB: [0, lowerRightLegDisplay.fHeight / 2 - 20 / utils_1.getfactor()],
        });
        rightElbowJoint.setLimits(0, Math.PI * 2 / 3);
        var bodies = [
            lowerRightArm, upperRightArm,
            lowerRightLeg, upperRightLeg, rightFoot,
            body,
            lowerLeftLeg, upperLeftLeg, leftFoot,
            lowerLeftArm, upperLeftArm,
            head,
        ];
        bodies.forEach(function (body) {
            world.addBody(body);
        });
        var joints = [
            leftAnkleJoint,
            leftKneeJoint,
            rightAnkleJoint,
            rightKneeJoint,
            headJoint,
            leftHipJoint,
            rightHipJoint,
            leftShoulderJoint,
            leftElbowJoint,
            rightShoulderJoint,
            rightElbowJoint,
            leftFootGroundCons,
            rightFootGroundCons,
        ];
        joints.forEach(function (joint) {
            world.addConstraint(joint);
        });
        for (var i = 0; i < bodyPartShapes.length; i++) {
            var s = bodyPartShapes[i];
            s.collisionGroup = collisionGroup;
            s.collisionMask = collisionMask;
        }
        this.foots = [leftFoot, rightFoot];
        this.lowerLegs = [lowerLeftLeg, lowerRightLeg];
        this.upperLegs = [upperLeftLeg, upperRightLeg];
        this.footGroundCons = [leftFootGroundCons, rightFootGroundCons];
    };
    Player.prototype.reset = function (revive) {
        var _this = this;
        if (revive === void 0) { revive = false; }
        if (revive) {
        }
        else {
            this.step = -1;
            this.safePos = 0;
            [
                'lowerLeftLeg',
                'upperLeftLeg',
                'lowerRightLeg',
                'upperRightLeg',
                'body',
                'head',
                'upperLeftArm',
                'lowerLeftArm',
                'upperRightArm',
                'lowerRightArm',
            ].forEach(function (partName) {
                var part = _this[partName];
                part.position[0] = _this.safePos + _this.originPos[partName][0];
            });
        }
        for (var i = 0; i < 2; i++) {
            var cons = this.footGroundCons[i];
            cons.pivotB[0] = this.foots[i].position[0] = this.safePos + (i == 0 ? -1 : 1) * this.shouldersDistance / 2;
            if (this.state == PlayerStat.FALL) {
                this.world.addConstraint(cons);
            }
        }
        this.switchFace('normal', false);
        this.setSkin('normal');
        this.state = PlayerStat.RELEASE;
    };
    Player.prototype.createDisplay = function (resName, offset) {
        if (offset === void 0) { offset = null; }
        var bmp = new PlayerPart_1.PlayerPart(resName);
        var anchorX = bmp.width / 2 + (offset ? offset.x : 0);
        var anchorY = bmp.height / 2 + (offset ? offset.y : 0);
        bmp.anchorTexture.set(anchorX / bmp.width, anchorY / bmp.height);
        return bmp;
    };
    Object.defineProperty(Player.prototype, "currentSide", {
        get: function () {
            return this.step % 2;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Player.prototype, "anotherSide", {
        get: function () {
            return (this.step + 1) % 2;
        },
        enumerable: true,
        configurable: true
    });
    Player.prototype.down = function () {
        if (this.state == PlayerStat.RISING) {
            return;
        }
        this.step++;
        var cons = this.footGroundCons[this.currentSide];
        this.world.removeConstraint(cons);
        this.state = PlayerStat.RISING;
    };
    Player.prototype.up = function () {
        if (this.state == PlayerStat.RELEASE) {
            return;
        }
        var side = this.currentSide;
        this.foots[side].velocity = [0, 0];
        this.body.velocity = [0, 0];
        var currentFoot = this.foots[side];
        var cons = this.footGroundCons[side];
        cons.pivotB[0] = currentFoot.position[0];
        this.world.addConstraint(cons);
        this.state = PlayerStat.RELEASE;
        setTimeout(this.onFootDown, 200);
    };
    Player.prototype.fall = function () {
        this.body.velocity = [0, -30];
        this.head.velocity = [-50, -50];
        this.world.removeConstraint(this.footGroundCons[0]);
        this.world.removeConstraint(this.footGroundCons[1]);
        this.foots[this.currentSide].velocity[0] = 60;
        this.foots[this.anotherSide].velocity[0] = 70;
        this.state = PlayerStat.FALL;
    };
    Player.prototype.switchFace = function (type, playAni) {
        if (playAni === void 0) { playAni = true; }
        var headDisplay = this.head.displays[0];
        headDisplay.switchFace(type, playAni);
    };
    Player.prototype.setSkin = function (name) {
        var _this = this;
        if (this.skin == name) {
            return;
        }
        this.skin = name;
        [
            'leftFoot',
            'lowerLeftLeg',
            'upperLeftLeg',
            'rightFoot',
            'lowerRightLeg',
            'upperRightLeg',
            'body',
            'upperLeftArm',
            'lowerLeftArm',
            'upperRightArm',
            'lowerRightArm',
        ].forEach(function (partName) {
            var part = _this[partName];
            part.displays[0].setSkin(name);
        });
    };
    Player.prototype.fade = function (alpha, animation) {
        var _this = this;
        if (animation === void 0) { animation = true; }
        [
            'leftFoot',
            'lowerLeftLeg',
            'upperLeftLeg',
            'rightFoot',
            'lowerRightLeg',
            'upperRightLeg',
            'body',
            'head',
            'upperLeftArm',
            'lowerLeftArm',
            'upperRightArm',
            'lowerRightArm',
        ].forEach(function (partName) {
            var display = _this[partName].displays[0];
            if (animation) {
                engine.Tween.get(display, null, null, true)
                    .to({ alpha: alpha }, 200);
            }
            else {
                display.alpha = alpha;
            }
        });
    };
    return Player;
}(engine.EventDispatcher));
exports.Player = Player;
