package org.odk.collect.android.views.colorpicker;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.Window;
import android.widget.Button;

import org.odk.collect.android.R;


/**
 * Dialog that allows a user to pick a color.
 */
public class ColorPickerDialog extends Dialog {


  private HuePicker huePicker;
  private OpacityPicker opacityPicker;
  private SatValPicker satValPicker;
  private View colorPreviewBox;
  private View oldColorPreviewBox;
  private Button pickButton;
  private Button cancelButton;


  private int initColor;

  private int mColor = Color.parseColor("#ffffffff");
  private String mHexVal = "#ffffffff";

  private OnColorPickedListener onColorPickedListener;

  private ColorPickerDialog(Context context) {
    super(context);
    init(context);
  }

  /**
   * Creates a Custom themed ColorPickerDialog <br/><br/> To create a light themed ColorPickerDialog, use
   * ColorPickerDialog.createColorPickerDialog(context,ColorPickerDialog.LIGHT_THEME); <br/><br/> To create a dark
   * themed ColorPickerDialog, use ColorPickerDialog.createColorPickerDialog(context,ColorPickerDialog.DARK_THEME);
   * <br/><br/> To create custom themes, create a new style with any of the ColorPicker themes as parent and use the
   * following attributes:<br/><br/> cp_showOpacityBar: boolean<br/> cp_showHexaDecimalValue: boolean<br/>
   * cp_showColorComponentsInfo: boolean<br/> cp_backgroundColor: color<br/> cp_hexaDecimalTextColor: color<br/>
   * cp_colorComponentsTextColor: color<br/> cp_positiveActionTextColor: color<br/> cp_negativeActionTextColor:
   * color<br/> cp_sliderThumbColor: color<br/>
   *
   * @param context
   *     Context
   *
   * @return Custom themed ColorPickerDialog
   */
  public static ColorPickerDialog createColorPickerDialog(Context context) {
    return new ColorPickerDialog(context);
  }

  @Override
  public void show() {
    super.show();
    reloadLastColor();
  }

  @Override
  public void dismiss() {
    super.dismiss();
    initColor = getLastColor(getContext());
  }

  private void init(final Context context) {
    getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.dialog_root);

    initColor = getLastColor(context);

    huePicker = (HuePicker) findViewById(R.id.hueBar);
    opacityPicker = (OpacityPicker) findViewById(R.id.opacityBar);
    satValPicker = (SatValPicker) findViewById(R.id.satValBox);
    colorPreviewBox = findViewById(R.id.colorPreviewBox);
    oldColorPreviewBox = findViewById(R.id.oldColorPreviewBox);
    pickButton = (Button) findViewById(R.id.pickButton);
    cancelButton = (Button) findViewById(R.id.cancelButton);

    huePicker.setOnHuePickedListener(new HuePicker.OnHuePickedListener() {
      @Override
      public void onPicked(float hue) {
        satValPicker.refreshSatValPicker(hue);
      }
    });

    huePicker.setMax(360);
    huePicker.setProgress(0);

    satValPicker.setOnColorSelectedListener(new SatValPicker.OnColorSelectedListener() {
      @Override
      public void onColorSelected(int color, String hexVal) {
        refreshPreviewBox(color, opacityPicker.getProgress());
        satValPicker.setCanUpdateHexVal(true);
      }
    });

    opacityPicker.setOnOpacityPickedListener(new OpacityPicker.OnOpacityPickedListener() {
      @Override
      public void onPicked(int opacity) {
        ColorDrawable colorDrawable = (ColorDrawable) colorPreviewBox.getBackground();
        if (colorDrawable == null) {
          return;
        }

        int color = colorDrawable.getColor();
        refreshPreviewBox(color, opacity);
        opacityPicker.setCanUpdateHexVal(true);
      }
    });


    pickButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        if (onColorPickedListener != null) {
          onColorPickedListener.onColorPicked(mColor, mHexVal);
        }
        Stools.saveLastColor(getContext(), mHexVal);
        dismiss();
      }
    });

    cancelButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        dismiss();
      }
    });
  }

  private void reloadLastColor() {
    reloadLastColor(initColor);
  }

  private void reloadLastColor(int current_color) {
    String lastHexVal = Stools.loadLastColor(getContext());
    if (lastHexVal != null) {
      int lastColor = Color.parseColor(lastHexVal);
      oldColorPreviewBox.setBackgroundColor(lastColor);
    }
    setCurrentColor(current_color);
  }

  private void setCurrentColor(int color) {
    setCurrentColor(color, true);
  }

  private void setCurrentColor(int color, boolean updateHexVal) {
    float[] hsv = new float[3];
    Color.colorToHSV(color, hsv);
    satValPicker.setCanUpdateHexVal(updateHexVal);
    opacityPicker.setCanUpdateHexVal(updateHexVal);

    satValPicker.setSaturationAndValue(hsv[1], hsv[2], false);
    if (huePicker.getProgress() != (int) hsv[0]) {
      huePicker.setProgress((int) hsv[0]);
    } else {
      satValPicker.refreshSatValPicker(huePicker.getProgress());
    }
    opacityPicker.setProgress(Color.alpha(color));
  }

  private void refreshPreviewBox(int color, int opacity) {
    color = Color.argb(opacity, Color.red(color), Color.green(color), Color.blue(color));
    colorPreviewBox.setBackgroundColor(color);

    mHexVal = "#" + Integer.toHexString(color);

    mColor = color;

    float[] hsv = new float[3];
    Color.colorToHSV(color, hsv);
  }


  /**
   * Register a callback to be invoked when the user picks a color by tapping the positive action
   *
   * @param onColorPickedListener
   *     Listener to call when color is picked
   */
  public void setOnColorPickedListener(OnColorPickedListener onColorPickedListener) {
    this.onColorPickedListener = onColorPickedListener;
  }


  /**
   * Gets the last picked color as an int
   *
   * @param context
   *     Context
   *
   * @return Returns the last picked color or Transparent color if the last picked color doesn't exist
   */
  public static int getLastColor(Context context) {
    String lastColorHex = Stools.loadLastColor(context);
    if (lastColorHex == null) {
      return Color.parseColor("#00ffffff");
    } else {
      return Color.parseColor(lastColorHex);
    }
  }

  /**
   * Interface definition for a callback to be invoked when the user picks a color by tapping the positive action
   */
  public interface OnColorPickedListener {
    /**
     * Called when the user picks a color by tapping the positive action
     *
     * @param color
     *     Color picked by the user
     * @param hexVal
     *     Color picked by the user in hexadecimal form
     */
    void onColorPicked(int color, String hexVal);
  }
}
