/*
 * Copyright 2016 Dolphin Emulator Project
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

package org.vita3k.emulator.overlay;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent;

/**
 * Custom {@link BitmapDrawable} that is capable
 * of storing it's own ID.
 */
public final class InputOverlayDrawableDpad
{
  // The legacy ID identifying what type of button this Drawable represents.
  private int mLegacyId;
  private int[] mControls = new int[4];
  private int mTrackId;
  private int mPreviousTouchX, mPreviousTouchY;
  private int mControlPositionX, mControlPositionY;
  private int mWidth;
  private int mHeight;
  private BitmapDrawable mDefaultStateBitmap;
  private BitmapDrawable mPressedOneDirectionStateBitmap;
  private BitmapDrawable mPressedTwoDirectionsStateBitmap;
  private int mPressState = STATE_DEFAULT;

  public static final int STATE_DEFAULT = 0;
  public static final int STATE_PRESSED_UP = 1;
  public static final int STATE_PRESSED_DOWN = 2;
  public static final int STATE_PRESSED_LEFT = 3;
  public static final int STATE_PRESSED_RIGHT = 4;
  public static final int STATE_PRESSED_UP_LEFT = 5;
  public static final int STATE_PRESSED_UP_RIGHT = 6;
  public static final int STATE_PRESSED_DOWN_LEFT = 7;
  public static final int STATE_PRESSED_DOWN_RIGHT = 8;

  /**
   * Constructor
   *
   * @param res                             {@link Resources} instance.
   * @param defaultStateBitmap              {@link Bitmap} of the default state.
   * @param pressedOneDirectionStateBitmap  {@link Bitmap} of the pressed state in one direction.
   * @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction.
   * @param legacyId                        Legacy identifier (ButtonType) for the up button.
   * @param upControl                       Control identifier for the up button.
   * @param downControl                     Control identifier for the down button.
   * @param leftControl                     Control identifier for the left button.
   * @param rightControl                    Control identifier for the right button.
   */
  public InputOverlayDrawableDpad(Resources res, Bitmap defaultStateBitmap,
          Bitmap pressedOneDirectionStateBitmap, Bitmap pressedTwoDirectionsStateBitmap,
          int legacyId, int upControl, int downControl, int leftControl, int rightControl)
  {
    mTrackId = -1;
    mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
    mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap);
    mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap);

    mWidth = mDefaultStateBitmap.getIntrinsicWidth();
    mHeight = mDefaultStateBitmap.getIntrinsicHeight();

    mLegacyId = legacyId;
    mControls[0] = upControl;
    mControls[1] = downControl;
    mControls[2] = leftControl;
    mControls[3] = rightControl;
  }

  public void draw(Canvas canvas)
  {
    int px = mControlPositionX + (getWidth() / 2);
    int py = mControlPositionY + (getHeight() / 2);
    switch (mPressState)
    {
      case STATE_DEFAULT:
        mDefaultStateBitmap.draw(canvas);
        break;
      case STATE_PRESSED_UP:
        mPressedOneDirectionStateBitmap.draw(canvas);
        break;
      case STATE_PRESSED_RIGHT:
        canvas.save();
        canvas.rotate(90, px, py);
        mPressedOneDirectionStateBitmap.draw(canvas);
        canvas.restore();
        break;
      case STATE_PRESSED_DOWN:
        canvas.save();
        canvas.rotate(180, px, py);
        mPressedOneDirectionStateBitmap.draw(canvas);
        canvas.restore();
        break;
      case STATE_PRESSED_LEFT:
        canvas.save();
        canvas.rotate(270, px, py);
        mPressedOneDirectionStateBitmap.draw(canvas);
        canvas.restore();
        break;
      case STATE_PRESSED_UP_LEFT:
        mPressedTwoDirectionsStateBitmap.draw(canvas);
        break;
      case STATE_PRESSED_UP_RIGHT:
        canvas.save();
        canvas.rotate(90, px, py);
        mPressedTwoDirectionsStateBitmap.draw(canvas);
        canvas.restore();
        break;
      case STATE_PRESSED_DOWN_RIGHT:
        canvas.save();
        canvas.rotate(180, px, py);
        mPressedTwoDirectionsStateBitmap.draw(canvas);
        canvas.restore();
        break;
      case STATE_PRESSED_DOWN_LEFT:
        canvas.save();
        canvas.rotate(270, px, py);
        mPressedTwoDirectionsStateBitmap.draw(canvas);
        canvas.restore();
        break;
    }
  }

  public int getLegacyId()
  {
    return mLegacyId;
  }

  /**
   * Gets one of the InputOverlayDrawableDpad's control IDs.
   */
  public int getControl(int direction)
  {
    return mControls[direction];
  }

  public void setTrackId(int trackId)
  {
    mTrackId = trackId;
  }

  public int getTrackId()
  {
    return mTrackId;
  }

  public void onConfigureTouch(MotionEvent event)
  {
    switch (event.getAction())
    {
      case MotionEvent.ACTION_DOWN:
        mPreviousTouchX = (int) event.getX();
        mPreviousTouchY = (int) event.getY();
        break;
      case MotionEvent.ACTION_MOVE:
        mControlPositionX += (int) event.getX() - mPreviousTouchX;
        mControlPositionY += (int) event.getY() - mPreviousTouchY;
        setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX,
                getHeight() + mControlPositionY);
        mPreviousTouchX = (int) event.getX();
        mPreviousTouchY = (int) event.getY();
        break;
    }
  }

  public void setPosition(int x, int y)
  {
    mControlPositionX = x;
    mControlPositionY = y;
  }

  public void setBounds(int left, int top, int right, int bottom)
  {
    mDefaultStateBitmap.setBounds(left, top, right, bottom);
    mPressedOneDirectionStateBitmap.setBounds(left, top, right, bottom);
    mPressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom);
  }

  public void setOpacity(int value)
  {
    mDefaultStateBitmap.setAlpha(value);
    mPressedOneDirectionStateBitmap.setAlpha(value);
    mPressedTwoDirectionsStateBitmap.setAlpha(value);
  }

  public Rect getBounds()
  {
    return mDefaultStateBitmap.getBounds();
  }

  public int getWidth()
  {
    return mWidth;
  }

  public int getHeight()
  {
    return mHeight;
  }

  public void setState(int pressState)
  {
    mPressState = pressState;
  }
}
