/*
 * Copyright (c) 2015 Diona Ltd.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of Diona
 * ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you
 * entered into with Diona.
 */
package org.odk.collect.android.views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

import org.odk.collect.android.application.Collect;
import org.odk.collect.android.utilities.FileUtils;

import java.io.File;

/**
 *
 */
public class DrawView extends View {
  private boolean isSignature;
  private Bitmap mBitmap;
  private Canvas mCanvas;
  private Path mCurrentPath;
  private Paint mBitmapPaint;
  private Paint paint;
  private Paint pointPaint;
  private File mBackgroundBitmapFile;

  public DrawView(final Context c) {
    super(c);
    isSignature = false;
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    mCurrentPath = new Path();
    setBackgroundColor(0xFFFFFFFF);
    mBackgroundBitmapFile = new File(Collect.TMPDRAWFILE_PATH);
  }

  public DrawView(Context c, boolean isSignature, File f) {
    this(c);
    this.isSignature = isSignature;
    mBackgroundBitmapFile = f;
  }

  public void reset() {
    Display display = ((WindowManager) getContext().getSystemService(
        Context.WINDOW_SERVICE)).getDefaultDisplay();
    int screenWidth = display.getWidth();
    int screenHeight = display.getHeight();
    resetImage(screenWidth, screenHeight);
  }

  public void resetImage(int w, int h) {
    if (mBackgroundBitmapFile.exists()) {
      mBitmap = FileUtils.getBitmapScaledToDisplay(
          mBackgroundBitmapFile, w, h).copy(
          Bitmap.Config.ARGB_8888, true);
      // mBitmap =
      // Bitmap.createScaledBitmap(BitmapFactory.decodeFile(mBackgroundBitmapFile.getPath()),
      // w, h, true);
      mCanvas = new Canvas(mBitmap);
    } else {
      mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
      mCanvas = new Canvas(mBitmap);
      mCanvas.drawColor(0xFFFFFFFF);
      if (isSignature) {
        drawSignLine();
      }
    }
  }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    resetImage(w, h);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawColor(0xFFAAAAAA);
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    canvas.drawPath(mCurrentPath, paint);
  }

  private float mX, mY;

  private void touch_start(float x, float y) {
    mCurrentPath.reset();
    mCurrentPath.moveTo(x, y);
    mX = x;
    mY = y;
  }

  public void drawSignLine() {
    mCanvas.drawLine(0, (int) (mCanvas.getHeight() * .7),
        mCanvas.getWidth(), (int) (mCanvas.getHeight() * .7), paint);
  }

  private void touch_move(float x, float y) {
    mCurrentPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
    mX = x;
    mY = y;
  }

  private void touch_up() {
    if (mCurrentPath.isEmpty()) {
      mCanvas.drawPoint(mX, mY, pointPaint);
    } else {
      mCurrentPath.lineTo(mX, mY);
      // commit the path to our offscreen
      mCanvas.drawPath(mCurrentPath, paint);
    }
    // kill this so we don't double draw
    mCurrentPath.reset();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        break;
      case MotionEvent.ACTION_MOVE:
        touch_move(x, y);
        invalidate();
        break;
      case MotionEvent.ACTION_UP:
        touch_up();
        invalidate();
        break;
    }
    return true;
  }

  public void setPaint(final Paint paint) {
    this.paint = paint;
  }

  public void setPointPaint(final Paint pointPaint) {
    this.pointPaint = pointPaint;
  }
}
