part of game;

const double _steeringThreshold = 0.0;
const double _steeringMax = 150.0;

// Random generator
Math.Random _rand = new Math.Random();

const double _gameSizeWidth = 1024.0;
const double _gameSizeHeight = 1024.0;

const double _shipRadius = 30.0;
const double _lrgAsteroidRadius = 40.0;
const double _medAsteroidRadius = 20.0;
const double _smlAsteroidRadius = 10.0;
const double _maxAsteroidSpeed = 1.0;

const int _lifeTimeLaser = 50;

const int _numStarsInStarField = 150;

const int _numFramesShieldActive = 60 * 5;
const int _numFramesShieldFlickers = 60;

class GameDemoWorld extends NodeWithSize {
  // Images
  sky.Image _imgNebula;

  SpriteSheet _spriteSheet;
  SpriteSheet _spriteSheetUI;

  Map<String,SoundEffect> _sounds;
  SoundEffectPlayer _soundPool = SoundEffectPlayer.sharedInstance();

  Navigator _navigator;

  // Inputs
  double _joystickX = 0.0;
  double _joystickY = 0.0;

  Node _gameLayer;

  Ship _ship;
  Sprite _shield;
  List<Asteroid> _asteroids = [];
  List<Laser> _lasers = [];
  StarField _starField;
  Nebula _nebula;

  // Game state
  int _numFrames = 0;
  bool _isGameOver = false;
  int _gameOverFrame;
  int _currentLevel = 0;

  // Heads up display
  Hud _hud;

  Function _gameOverCallback;

  GameDemoWorld(App app, this._navigator, ImageMap images, this._spriteSheet, this._spriteSheetUI, this._sounds, this._gameOverCallback) : super(new Size(_gameSizeWidth, _gameSizeHeight)) {
    // Fetch images
    _imgNebula = images["assets/nebula.png"];

    _gameLayer = new Node();
    this.addChild(_gameLayer);
    // Add ship
    addShip();

    // Add background
    Sprite sprtBackground = new Sprite.fromImage(images["assets/starfield.png"]);
    sprtBackground.position = new Point(512.0, 512.0);
    sprtBackground.zPosition = -3.0;
    addChild(sprtBackground);

    // Add starfield
    _starField = new StarField(_spriteSheet, _numStarsInStarField);
    _starField.zPosition = -2.0;
    addChild(_starField);

    // Add nebula
    addNebula();

    userInteractionEnabled = true;
    handleMultiplePointers = true;

    _hud = new Hud(_spriteSheetUI);
    _hud.zPosition = 1000.0;
    addChild(_hud);

    // Setup level
    setupLevel(0);
  }

  void setupLevel(int level) {
    int numLargeAsteroids = 5 + level * 2;
    int numMediumAsteroids = 5 + level * 2;

    // Add some asteroids to the game world
    for (int i = 0; i < numLargeAsteroids; i++) {
      addAsteroid(AsteroidSize.large);
    }
    for (int i = 0; i < numMediumAsteroids; i++) {
      addAsteroid(AsteroidSize.medium);
    }

    _numFrames = 0;
    _shield.visible = true;
  }

  // Methods for adding game objects

  void addAsteroid(AsteroidSize size, [Point pos]) {
    Asteroid asteroid = new Asteroid(_spriteSheet, size);
    asteroid.zPosition = 1.0;
    if (pos != null) asteroid.position = pos;
    _gameLayer.addChild(asteroid);
    _asteroids.add(asteroid);

    // Animate asteroid into the scene
    Action action = new ActionTween((a) => asteroid.scale = a, 0.0, 1.0, 1.0, bounceOut);
    _gameLayer.actions.run(action);
  }

  void addShip() {
    Ship ship = new Ship(_spriteSheet["ship.png"]);
    ship.zPosition = 10.0;
    _gameLayer.addChild(ship);
    _ship = ship;

    _shield = new Sprite(_spriteSheet["shield.png"]);
    _shield.zPosition = 11.0;
    _shield.scale = 0.5;
    _shield.transferMode = sky.TransferMode.plus;
    _gameLayer.addChild(_shield);

    Action rotate = new ActionRepeatForever(new ActionTween((a) => _shield.rotation = a, 0.0, 360.0, 1.0));
    actions.run(rotate);
  }

  void addLaser() {
    Laser laser = new Laser(_spriteSheet["laser.png"], _ship);
    laser.zPosition = 8.0;
    laser.constrainProportions = true;
    _lasers.add(laser);
    _gameLayer.addChild(laser);

    _soundPool.play(_sounds["laser"]);
  }

  void addNebula() {
    _nebula = new Nebula.withImage(_imgNebula);
    _gameLayer.addChild(_nebula);
  }

  void addExplosion(AsteroidSize asteroidSize, Point position) {
    Node explosionNode = new Node();

    // Add particles
    ParticleSystem particlesDebris = new ParticleSystem(
        _spriteSheet["explosion_particle.png"],
        rotateToMovement: true,
        startRotation:90.0,
        startRotationVar: 0.0,
        endRotation: 90.0,
        startSize: 0.3,
        startSizeVar: 0.1,
        endSize: 0.3,
        endSizeVar: 0.1,
        numParticlesToEmit: 25,
        emissionRate:1000.0,
        greenVar: 127,
        redVar: 127
    );
    particlesDebris.zPosition = 1010.0;
    explosionNode.addChild(particlesDebris);

    ParticleSystem particlesFire = new ParticleSystem(
      _spriteSheet["fire_particle.png"],
      colorSequence: new ColorSequence([new Color(0xffffff33), new Color(0xffff3333), new Color(0x00ff3333)], [0.0, 0.5, 1.0]),
      numParticlesToEmit: 25,
      emissionRate: 1000.0,
      startSize: 0.5,
      startSizeVar: 0.1,
      endSize: 0.5,
      endSizeVar: 0.1,
      posVar: new Point(10.0, 10.0),
      speed: 10.0,
      speedVar: 5.0
    );
    particlesFire.zPosition = 1011.0;
    explosionNode.addChild(particlesFire);


    // Add ring
    Sprite sprtRing = new Sprite(_spriteSheet["explosion_ring.png"]);
    sprtRing.transferMode = sky.TransferMode.plus;
    explosionNode.addChild(sprtRing);

    Action scale = new ActionTween( (a) => sprtRing.scale = a, 0.2, 1.0, 1.5);
    Action scaleAndRemove = new ActionSequence([scale, new ActionRemoveNode(sprtRing)]);
    Action fade = new ActionTween( (a) => sprtRing.opacity = a, 1.0, 0.0, 1.5);
    actions.run(scaleAndRemove);
    actions.run(fade);

    // Add streaks
    for (int i = 0; i < 5; i++) {
      Sprite sprtFlare = new Sprite(_spriteSheet["explosion_flare.png"]);
      sprtFlare.pivot = new Point(0.3, 1.0);
      sprtFlare.scaleX = 0.3;
      sprtFlare.transferMode = sky.TransferMode.plus;
      sprtFlare.rotation = _rand.nextDouble() * 360.0;
      explosionNode.addChild(sprtFlare);

      double multiplier = _rand.nextDouble() * 0.3 + 1.0;

      Action scale = new ActionTween( (a) => sprtFlare.scaleY = a, 0.3 * multiplier, 0.8, 1.5 * multiplier);
      Action scaleAndRemove = new ActionSequence([scale, new ActionRemoveNode(sprtFlare)]);
      Action fadeIn = new ActionTween( (a) => sprtFlare.opacity = a, 0.0, 1.0, 0.5 * multiplier);
      Action fadeOut = new ActionTween( (a) => sprtFlare.opacity = a, 1.0, 0.0, 1.0 * multiplier);
      Action fadeInOut = new ActionSequence([fadeIn, fadeOut]);
      actions.run(scaleAndRemove);
      actions.run(fadeInOut);
    }

    explosionNode.position = position;
    explosionNode.zPosition = 1010.0;

    if (asteroidSize == AsteroidSize.large) {
      explosionNode.scale = 1.5;
    }

    _gameLayer.addChild(explosionNode);

    _soundPool.play(_sounds["explosion"]);
  }

  void update(double dt) {
    // Move asteroids
    for (Asteroid asteroid in _asteroids) {
      asteroid.position = pointAdd(asteroid.position, asteroid._movementVector);
    }

    // Move lasers and remove expired lasers
    for (int i = _lasers.length - 1; i >= 0; i--) {
      Laser laser = _lasers[i];
      laser.move();
      if (laser._frameCount > _lifeTimeLaser) {
        laser.removeFromParent();
        _lasers.removeAt(i);
      }
    }

    // Apply thrust to ship
    if (_joystickX != 0.0 || _joystickY != 0.0) {
      _ship.thrust(_joystickX, _joystickY);
    }

    // Move ship
    _ship.move();
    _shield.position = _ship.position;

    // Check collisions between asteroids and lasers
    for (int i = _lasers.length -1; i >= 0; i--) {
      // Iterate over all the lasers
      Laser laser = _lasers[i];

      for (int j = _asteroids.length - 1; j >= 0; j--) {
        // Iterate over all the asteroids
        Asteroid asteroid = _asteroids[j];

        // Check for collision
        if (pointQuickDist(laser.position, asteroid.position) < laser.radius + asteroid.radius) {
          // Remove laser
          laser.removeFromParent();
          _lasers.removeAt(i);

          // Add asteroids and explosions
          if (asteroid._asteroidSize == AsteroidSize.large) {
            for (int a = 0; a < 3; a++) addAsteroid(AsteroidSize.medium, asteroid.position);
          }
          else if (asteroid._asteroidSize == AsteroidSize.medium) {
            for (int a = 0; a < 5; a++) addAsteroid(AsteroidSize.small, asteroid.position);
          }

          addExplosion(asteroid._asteroidSize, asteroid.position);

          // Remove asteroid
          asteroid.removeFromParent();
          _asteroids.removeAt(j);

          // Scoring
          if (asteroid._asteroidSize == AsteroidSize.large)
            addScore(100);
          else if (asteroid._asteroidSize == AsteroidSize.medium)
            addScore(50);
          else
            addScore(10);
          break;
        }
      }
    }

    // Check collisions between asteroids and ship
    if (_numFrames > _numFramesShieldActive) {
      // Shield is no longer active

      for (int i = _asteroids.length - 1; i >= 0; i--) {
        // Iterate over all the asteroids
        Asteroid asteroid = _asteroids[i];

        if (pointQuickDist(asteroid.position, _ship.position) < asteroid.radius + _ship.radius) {
          killShip();
        }
      }
    }

    // Move objects to center camera and warp objects around the edges
    centerCamera();
    warpObjects();

    // Check for level up
    if (_asteroids.length == 0) {
      _currentLevel++;
      setupLevel(_currentLevel);
    }

    // Update shield
    if (_numFrames > _numFramesShieldActive) _shield.visible = false;
    else if (_numFrames > _numFramesShieldActive - _numFramesShieldFlickers) _shield.visible = !_shield.visible;

    // Check for exit back to main screen
    if (_isGameOver && _numFrames - _gameOverFrame == 60) {
      _navigator.pop();
    }

    _numFrames++;
  }

  void centerCamera() {
    const cameraDampening = 0.1;
    Point delta = new Point(_gameSizeWidth/2 - _ship.position.x, _gameSizeHeight/2 - _ship.position.y);
    delta = pointMult(delta, cameraDampening);

    for (Node child in _gameLayer.children) {
      child.position = pointAdd(child.position, delta);
    }

    // Update starfield
    _starField.move(delta.x, delta.y);
  }

  void warpObjects() {
    for (Node child in _gameLayer.children) {
      if (child.position.x < 0) child.position = pointAdd(child.position, new Point(_gameSizeWidth, 0.0));
      if (child.position.x >= _gameSizeWidth) child.position = pointAdd(child.position, new Point(-_gameSizeWidth, 0.0));
      if (child.position.y < 0) child.position = pointAdd(child.position, new Point(0.0, _gameSizeHeight));
      if (child.position.y >= _gameSizeHeight) child.position = pointAdd(child.position, new Point(0.0, -_gameSizeHeight));
    }
  }

  void killShip() {
    if (_isGameOver) return;

    // Set game over
    _isGameOver = true;
    _gameOverFrame = _numFrames;
    _gameOverCallback(_hud.score);

    // Remove the ship
    _ship.visible = false;

    // Add an explosion
    addExplosion(AsteroidSize.large, _ship.position);
  }

  // Handling controls

  void controlSteering(double x, double y) {
    // Reset controls if it's game over
    if (_isGameOver) {
      x = y = 0.0;
    }

    _joystickX = x;
    _joystickY = y;
  }

  void controlFire() {
    // Don't shoot if it's game over
    if (_isGameOver) return;

    addLaser();
  }

  // Handle pointer events

  int _firstPointer = -1;
  int _secondPointer = -1;
  Point _firstPointerDownPos;

  bool handleEvent(SpriteBoxEvent event) {

    Point pointerPos = convertPointToNodeSpace(event.boxPosition);
    int pointer = event.pointer;

    switch (event.type) {
      case 'pointerdown':
        if (_firstPointer == -1) {
          // Assign the first pointer
          _firstPointer = pointer;
          _firstPointerDownPos = pointerPos;
        }
        else if (_secondPointer == -1) {
          // Assign second pointer
          _secondPointer = pointer;
          controlFire();
        }
        else {
          // There is a pointer used for steering, let's fire instead
          controlFire();
        }
        break;
      case 'pointermove':
        if (pointer == _firstPointer) {
          // Handle turning control
          double joystickX = 0.0;
          double deltaX = pointerPos.x - _firstPointerDownPos.x;
          if (deltaX > _steeringThreshold || deltaX < -_steeringThreshold) {
            joystickX = (deltaX - _steeringThreshold)/(_steeringMax - _steeringThreshold);
            if (joystickX > 1.0) joystickX = 1.0;
            if (joystickX < -1.0) joystickX = -1.0;
          }

          double joystickY = 0.0;
          double deltaY = pointerPos.y - _firstPointerDownPos.y;
          if (deltaY > _steeringThreshold || deltaY < -_steeringThreshold) {
            joystickY = (deltaY - _steeringThreshold)/(_steeringMax - _steeringThreshold);
            if (joystickY > 1.0) joystickY = 1.0;
            if (joystickY < -1.0) joystickY = -1.0;
          }

          controlSteering(joystickX, joystickY);
        }
        break;
      case 'pointerup':
      case 'pointercancel':
        if (pointer == _firstPointer) {
          // Un-assign the first pointer
          _firstPointer = -1;
          _firstPointerDownPos = null;
          controlSteering(0.0, 0.0);
        }
        else if (pointer == _secondPointer) {
          _secondPointer = -1;
        }
        break;
      default:
        break;
    }
    return true;
  }

  // Scoring and HUD
  void addScore(int score) {
    _hud.score += score;
  }
}

// Game objects

enum AsteroidSize {
  small,
  medium,
  large,
}

class Asteroid extends Sprite {
  Point _movementVector;
  AsteroidSize _asteroidSize;
  double _radius;

  double get radius {
    if (_radius != null) return _radius;
    if (_asteroidSize == AsteroidSize.small) _radius = _smlAsteroidRadius;
    else if (_asteroidSize == AsteroidSize.medium) _radius = _medAsteroidRadius;
    else if (_asteroidSize == AsteroidSize.large) _radius = _lrgAsteroidRadius;
    return _radius;
  }

  Asteroid(SpriteSheet spriteSheet, AsteroidSize this._asteroidSize) {
    size = new Size(radius * 2.0, radius * 2.0);
    position = new Point(_gameSizeWidth * _rand.nextDouble(), _gameSizeHeight * _rand.nextDouble());
    rotation = 360.0 * _rand.nextDouble();

    if (_asteroidSize == AsteroidSize.small) {
      texture = spriteSheet["asteroid_small_${_rand.nextInt(2)}.png"];
    } else {
      texture = spriteSheet["asteroid_big_${_rand.nextInt(2)}.png"];
    }

    _movementVector = new Point(_rand.nextDouble() * _maxAsteroidSpeed * 2 - _maxAsteroidSpeed,
                                _rand.nextDouble() * _maxAsteroidSpeed * 2 - _maxAsteroidSpeed);

    userInteractionEnabled = true;

    // Rotate forever
    double direction = (_rand.nextBool()) ? 360.0 : -360.0;
    ActionTween rot = new ActionTween( (a) => rotation = a, 0.0, direction, 2.0 * _rand.nextDouble() + 2.0);
    ActionRepeatForever repeat = new ActionRepeatForever(rot);
    actions.run(repeat);
  }

  bool handleEvent(SpriteBoxEvent event) {
    if (event.type == "pointerdown") {
      actions.stopWithTag("fade");
      colorOverlay = new Color(0x99ffffff);
    }
    else if (event.type == "pointerup") {
      // Fade out the color overlay
      Action fadeOut = new ActionTween((a) => this.colorOverlay = a, new Color(0x99ffffff), new Color(0x00ffffff), 1.0);
      Action fadeOutAndRemove = new ActionSequence([fadeOut, new ActionCallFunction(() => this.colorOverlay = null)]);
      actions.run(fadeOutAndRemove, "fade");
    }
    return false;
  }
}

class Ship extends Sprite {
  Vector2 _movementVector;
  double _rotationTarget;
  double radius = _shipRadius;

  Ship(Texture img) : super(img) {
    _movementVector = new Vector2.zero();
    rotation = _rotationTarget = 270.0;

    // Create sprite
    size = new Size(_shipRadius * 2.0, _shipRadius * 2.0);
    position = new Point(_gameSizeWidth/2.0, _gameSizeHeight/2.0);
  }

  void thrust(double x, double y) {
    _rotationTarget = convertRadians2Degrees(Math.atan2(y, x));
    Vector2 directionVector = new Vector2(x, y).normalize();
    _movementVector.addScaled(directionVector, 1.0);
  }

  void move() {
    position = new Point(position.x + _movementVector[0], position.y + _movementVector[1]);
    _movementVector.scale(0.9);

    rotation = dampenRotation(rotation, _rotationTarget, 0.1);
  }
}

class Laser extends Sprite {
  int _frameCount = 0;
  Point _movementVector;
  double radius = 20.0;

  Laser(Texture img, Ship ship) : super(img) {
    size = new Size(30.0, 30.0);
    position = ship.position;
    rotation = ship.rotation + 90.0;
    transferMode = sky.TransferMode.plus;
    double rotRadians = convertDegrees2Radians(rotation);
    _movementVector = pointMult(new Point(Math.sin(rotRadians), -Math.cos(rotRadians)), 10.0);
    _movementVector = new Point(_movementVector.x + ship._movementVector[0], _movementVector.y + ship._movementVector[1]);
  }

  void move() {
    position = pointAdd(position, _movementVector);
    _frameCount++;
  }
}

// Background starfield

class StarField extends NodeWithSize {
  sky.Image _image;
  int _numStars;
  bool _autoScroll;
  List<Point> _starPositions;
  List<double> _starScales;
  List<Rect> _rects;
  List<Color> _colors;
  Paint _paint = new Paint()
    ..setFilterQuality(sky.FilterQuality.low)
    ..isAntiAlias = false
    ..setTransferMode(sky.TransferMode.plus);

  StarField(SpriteSheet spriteSheet, this._numStars, [this._autoScroll = false]) : super(new Size(1024.0, 1024.0)) {
    _starPositions = [];
    _starScales = [];
    _colors = [];
    _rects = [];

    for (int i  = 0; i < _numStars; i++) {
      _starPositions.add(new Point(_rand.nextDouble() * _gameSizeWidth, _rand.nextDouble() * _gameSizeHeight));
      _starScales.add(_rand.nextDouble());
      _colors.add(new Color.fromARGB((255.0 * (_rand.nextDouble() * 0.5 + 0.5)).toInt(), 255, 255, 255));
      _rects.add(spriteSheet["star_${_rand.nextInt(2)}.png"].frame);
    }

    _image = spriteSheet.image;
  }

  void paint(PaintingCanvas canvas) {
    // Create a transform for each star
    List<sky.RSTransform> transforms = [];
    for (int i = 0; i < _numStars; i++) {
      sky.RSTransform transform = new sky.RSTransform(_starScales[i], 0.0, _starPositions[i].x, _starPositions[i].y);
      transforms.add(transform);
    }

    // Draw the stars
    canvas.drawAtlas(_image, transforms, _rects, _colors, sky.TransferMode.modulate, null, _paint);
  }

  void move(double dx, double dy) {
    for (int i  = 0; i < _numStars; i++) {
      double xPos = _starPositions[i].x;
      double yPos = _starPositions[i].y;
      double scale = _starScales[i];

      xPos += dx * scale;
      yPos += dy * scale;

      if (xPos >= _gameSizeWidth) xPos -= _gameSizeWidth;
      if (xPos < 0) xPos += _gameSizeWidth;
      if (yPos >= _gameSizeHeight) yPos -= _gameSizeHeight;
      if (yPos < 0) yPos += _gameSizeHeight;

      _starPositions[i] = new Point(xPos, yPos);
    }
  }

  void update(double dt) {
    if (_autoScroll) {
      move(dt * 100.0, 0.0);
    }
  }
}

class Hud extends NodeWithSize {
  SpriteSheet spriteSheetUI;
  Sprite sprtBgScore;
  Sprite sprtBgShield;
  bool _dirtyScore = true;

  int _score = 0;

  int get score => _score;

  set score(int score) {
    _score = score;
    _dirtyScore = true;
  }

  Hud(this.spriteSheetUI) : super(Size.zero) {
    pivot = Point.origin;

    sprtBgScore = new Sprite(spriteSheetUI["scoreboard.png"]);
    sprtBgScore.pivot = new Point(1.0, 0.0);
    sprtBgScore.scale = 0.6;
    addChild(sprtBgScore);

    sprtBgShield = new Sprite(spriteSheetUI["bar_shield.png"]);
    sprtBgShield.pivot = Point.origin;
    sprtBgShield.scale = 0.6;
    // TODO: Add shield
    //addChild(sprtBgShield);
  }

  void spriteBoxPerformedLayout() {
    // Set the size and position of HUD display
    position = spriteBox.visibleArea.topLeft;
    size = spriteBox.visibleArea.size;

    // Position hud objects
    sprtBgShield.position = new Point(20.0, 20.0);
    sprtBgScore.position = new Point(size.width - 20.0, 20.0);
  }

  void update(double dt) {
    // Update score
    if (_dirtyScore) {

      sprtBgScore.removeAllChildren();

      String scoreStr = _score.toString();
      double xPos = -50.0;
      for (int i = scoreStr.length - 1; i >= 0; i--) {
        String numStr = scoreStr.substring(i, i + 1);
        Sprite numSprt = new Sprite(spriteSheetUI["number_$numStr.png"]);
        numSprt.position = new Point(xPos, 49.0);
        sprtBgScore.addChild(numSprt);
        xPos -= 37.0;
      }
      _dirtyScore = false;
    }
    // Update power bar
  }
}

class Nebula extends Node {

  Nebula.withImage(sky.Image img) {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        Sprite sprt = new Sprite.fromImage(img);
        sprt.transferMode = sky.TransferMode.plus;
        sprt.pivot = Point.origin;
        sprt.position = new Point(i * _gameSizeWidth - _gameSizeWidth, j * _gameSizeHeight - _gameSizeHeight);
        addChild(sprt);
      }
    }
  }
}

// Convenience methods

Point pointAdd(Point a, Point b) {
  return new Point(a.x+ b.x, a.y + b.y);
}

Point pointMult(Point a, double multiplier) {
  return new Point(a.x * multiplier, a.y * multiplier);
}

double dampenRotation(double src, double dst, double dampening) {
  double delta = dst - src;
  while (delta > 180.0) delta -= 360;
  while (delta < -180) delta += 360;
  delta *= dampening;

  return src + delta;
}

double pointQuickDist(Point a, Point b) {
  double dx = a.x - b.x;
  double dy = a.y - b.y;
  if (dx < 0.0) dx = -dx;
  if (dy < 0.0) dy = -dy;
  if (dx > dy) {
    return dx + dy/2.0;
  }
  else {
    return dy + dx/2.0;
  }
}
