// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.reviewit.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.reviewit.R;
import com.google.reviewit.app.Change;
import com.google.reviewit.util.WidgetUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static com.google.common.base.Preconditions.checkState;
import static com.google.reviewit.util.LayoutUtil.matchAndWrapLayout;
import static com.google.reviewit.util.LayoutUtil.matchLayout;

/**
 * View to post a review on a change (summary comment + Code-Review vote).
 */
public class PostReviewView extends LinearLayout {
  private final WidgetUtil widgetUtil;
  private final List<VotingButton> votingButtons = new ArrayList<>();
  private final ImageView emoticon;

  private Change change;
  private OnVoteListener onVoteListener = null;

  public PostReviewView(Context context) {
    this(context, null);
  }

  public PostReviewView(Context context, AttributeSet attrs) {
    super(context, attrs);

    this.widgetUtil = new WidgetUtil(context);

    setOrientation(VERTICAL);

    RelativeLayout votingPanel = new RelativeLayout(context);
    votingPanel.setLayoutParams(new RelativeLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, widgetUtil.dpToPx(200)));
    addView(votingPanel);

    VotingButton voteMinus1 = new VotingButton(context,
        Background.Corner.LEFT_TOP,
        R.drawable.ic_exposure_neg_1_white_48dp,
        R.drawable.ic_sentiment_dissatisfied_white_48dp,
        R.color.votingNegative,
        R.color.votingNegativeSelected,
        -1);
    VotingButton voteMinus2 = new VotingButton(context,
        Background.Corner.LEFT_BOTTOM,
        R.drawable.ic_exposure_neg_2_white_48dp,
        R.drawable.ic_sentiment_very_dissatisfied_white_48dp,
        R.color.votingNegative,
        R.color.votingNegativeSelected,
        -2);
    VotingButton votePlus1 = new VotingButton(context,
        Background.Corner.RIGHT_TOP,
        R.drawable.ic_exposure_plus_1_white_48dp,
        R.drawable.ic_sentiment_satisfied_white_48dp,
        R.color.votingPositive,
        R.color.votingPositiveSelected,
        1);
    VotingButton votePlus2 = new VotingButton(context,
        Background.Corner.RIGHT_BOTTOM,
        R.drawable.ic_exposure_plus_2_white_48dp,
        R.drawable.ic_sentiment_very_satisfied_white_48dp,
        R.color.votingPositive,
        R.color.votingPositiveSelected,
        2);
    votingButtons.addAll(
        Arrays.asList(voteMinus1, voteMinus2, votePlus1, votePlus2));

    LinearLayout votePanels = new LinearLayout(context);
    votePanels.setLayoutParams(matchLayout());
    votePanels.setOrientation(LinearLayout.VERTICAL);
    votingPanel.addView(votePanels);

    LinearLayout votePanel1 = new LinearLayout(context);
    votePanel1.setLayoutParams(matchAndWrapLayout());
    votePanel1.setOrientation(LinearLayout.HORIZONTAL);
    votePanels.addView(votePanel1);
    votePanel1.addView(voteMinus1);
    votePanel1.addView(votePlus1);

    LinearLayout votePanel2 = new LinearLayout(context);
    votePanel2.setLayoutParams(matchAndWrapLayout());
    votePanel2.setOrientation(LinearLayout.HORIZONTAL);
    votePanels.addView(votePanel2);
    votePanel2.addView(voteMinus2);
    votePanel2.addView(votePlus2);

    emoticon = new ImageView(context);
    RelativeLayout.LayoutParams emoticonParams =
        new RelativeLayout.LayoutParams(
            widgetUtil.dpToPx(110), widgetUtil.dpToPx(110));
    emoticonParams.addRule(RelativeLayout.CENTER_IN_PARENT,
        RelativeLayout.TRUE);
    emoticon.setLayoutParams(emoticonParams);
    emoticon.setImageDrawable(
        widgetUtil.getDrawable(R.drawable.ic_sentiment_neutral_white_48dp));
    emoticon.setColorFilter(
        widgetUtil.color(R.color.votingNeutral));
    votingPanel.addView(emoticon);

    setOnTouchListener(new OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        Rect emoticonBounds = new Rect(emoticon.getLeft(), emoticon.getTop(),
            emoticon.getRight(), emoticon.getBottom());
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
          case MotionEvent.ACTION_MOVE:
            if (applyEvent(emoticonBounds, event)) {
              emoticon.setImageDrawable(widgetUtil.getDrawable(
                  R.drawable.ic_sentiment_neutral_white_48dp));
              emoticon.setColorFilter(widgetUtil.color(R.color.votingNeutral));
              for (VotingButton b : votingButtons) {
                if (!b.isDisabled()) {
                  WidgetUtil.setBackground(b, b.getBackgroundDrawable());
                }
              }
            } else {
              boolean selected = false;
              for (VotingButton b : votingButtons) {
                if (!b.isDisabled()) {
                  if (applyEvent(b, event)) {
                    WidgetUtil.setBackground(b,
                        b.getBackgroundDrawableSelected());
                    b.applyIcon(emoticon);
                    selected = true;
                  } else {
                    WidgetUtil.setBackground(b, b.getBackgroundDrawable());
                  }
                }
                if (!selected) {
                  emoticon.setImageDrawable(widgetUtil.getDrawable(
                      R.drawable.ic_sentiment_neutral_white_48dp));
                  emoticon.setColorFilter(
                      widgetUtil.color(R.color.votingNeutral));
                }
              }
            }
            break;
          case MotionEvent.ACTION_UP:
            checkState(change != null, "Change not set");
            Integer vote = null;
            if (applyEvent(emoticonBounds, event)) {
              vote = 0;
            } else {
              for (VotingButton b : votingButtons) {
                if (!b.isDisabled() && applyEvent(b, event)) {
                  vote = b.getVote();
                }
              }
            }
            if (vote != null && onVoteListener != null) {
              onVoteListener.vote(vote);
            }
            break;
          default:
            break;
        }
        return true;
      }

      private boolean applyEvent(VotingButton b, MotionEvent event) {
        return applyEvent(b.getBounds(), event);
      }

      private boolean applyEvent(Rect bounds, MotionEvent event) {
        return bounds.contains((int) event.getX() - getPaddingLeft(),
            (int) event.getY() - getPaddingTop());
      }
    });
  }

  public void setChange(Change change) {
    this.change = change;

    Collection<Integer> voteableValues = Collections2.transform(
        change.info.permittedLabels.get("Code-Review"),
        new Function<String, Integer>() {
      @Override
      public Integer apply(String value) {
        return Integer.parseInt(value.trim());
      }
    });
    for (VotingButton b : votingButtons) {
      if (!voteableValues.contains(b.getVote())) {
        b.setDisabled(true);
        WidgetUtil.setBackground(b, b.getBackgroundDrawableDisabled());
      }
    }
  }

  public void select(int vote) {
    for (VotingButton b : votingButtons) {
      if (b.getVote() == vote) {
        WidgetUtil.setBackground(b, b.getBackgroundDrawableSelected());
        b.applyIcon(emoticon);
      }
    }
  }

  public void setOnVoteListener(OnVoteListener onVoteListener) {
    this.onVoteListener = onVoteListener;
  }

  private class VotingButton extends LinearLayout {
    private final Background.Corner corner;
    private final Background background;
    private final Background backgroundSelected;
    private final Background backgroundDisabled;
    private final
    @ColorRes
    int colorSelected;
    private final
    @DrawableRes
    int iconResSelected;
    private final int vote;
    private boolean disabled;

    public VotingButton(
        Context context, Background.Corner corner, @DrawableRes int iconRes,
        @DrawableRes int iconResSelected, @ColorRes int color,
        @ColorRes int colorSelected, int vote) {
      super(context);
      LinearLayout.LayoutParams params =
          new LinearLayout.LayoutParams(
              ViewGroup.LayoutParams.WRAP_CONTENT, widgetUtil.dpToPx(100));
      params.weight = 1;
      setLayoutParams(params);

      this.corner = corner;
      this.background = new Background(widgetUtil.color(color), corner);
      this.backgroundSelected = new Background(
          widgetUtil.color(colorSelected), corner);
      this.backgroundDisabled = new Background(
          widgetUtil.color(R.color.disabled), corner);
      this.colorSelected = colorSelected;
      this.iconResSelected = iconResSelected;
      this.vote = vote;

      WidgetUtil.setBackground(this, background);

      ImageView icon = new ImageView(context);
      icon.setImageDrawable(widgetUtil.getDrawable(iconRes));
      LinearLayout.LayoutParams iconParams =
          new LinearLayout.LayoutParams(
              widgetUtil.dpToPx(60), widgetUtil.dpToPx(60));
      switch (corner) {
        case LEFT_TOP:
          iconParams.topMargin = widgetUtil.dpToPx(8);
          iconParams.leftMargin = widgetUtil.dpToPx(8);
          break;
        case LEFT_BOTTOM:
          iconParams.bottomMargin = widgetUtil.dpToPx(8);
          iconParams.leftMargin = widgetUtil.dpToPx(8);
          iconParams.gravity = Gravity.BOTTOM;
          break;
        case RIGHT_TOP:
          iconParams.topMargin = widgetUtil.dpToPx(8);
          iconParams.rightMargin = widgetUtil.dpToPx(8);
          setGravity(Gravity.END);
          break;
        case RIGHT_BOTTOM:
          iconParams.bottomMargin = widgetUtil.dpToPx(8);
          iconParams.rightMargin = widgetUtil.dpToPx(8);
          iconParams.gravity = Gravity.BOTTOM;
          setGravity(Gravity.END);
          break;
        default:
          break;
      }
      icon.setLayoutParams(iconParams);
      addView(icon);
    }

    public void setDisabled(boolean disabled) {
      this.disabled = disabled;
    }

    public boolean isDisabled() {
      return disabled;
    }

    public int getVote() {
      return vote;
    }

    public Background getBackgroundDrawable() {
      return background;
    }

    public Background getBackgroundDrawableSelected() {
      return backgroundSelected;
    }

    public Background getBackgroundDrawableDisabled() {
      return backgroundDisabled;
    }

    public void applyIcon(ImageView image) {
      image.setImageDrawable(widgetUtil.getDrawable(iconResSelected));
      image.setColorFilter(widgetUtil.color(colorSelected));
    }

    public Rect getBounds() {
      if (corner == Background.Corner.LEFT_BOTTOM
          || corner == Background.Corner.RIGHT_BOTTOM) {
        return new Rect(getLeft(), getHeight() + getTop(), getRight(),
            getHeight() + getBottom());
      } else {
        return new Rect(getLeft(), getTop(), getRight(), getBottom());
      }
    }
  }

  private static class Background extends Drawable {
    public enum Corner {
      LEFT_TOP,
      LEFT_BOTTOM,
      RIGHT_TOP,
      RIGHT_BOTTOM
    }

    private final int color;
    private final Corner corner;

    public Background(int color, Corner corner) {
      this.color = color;
      this.corner = corner;
    }

    @Override
    public void draw(Canvas canvas) {
      canvas.save();

      Paint paint = new Paint();
      paint.setColor(color);
      paint.setStyle(Paint.Style.FILL);

      Rect bounds = getBounds();
      float lamda = (float) Math.toDegrees(
          Math.atan((float) (bounds.height()) / (float) (bounds.width())));
      switch (corner) {
        case LEFT_TOP:
          lamda = 180 - lamda;
          break;
        case LEFT_BOTTOM:
          // lamda = lamda;
          break;
        case RIGHT_TOP:
          lamda = 180 + lamda;
          break;
        case RIGHT_BOTTOM:
          lamda = -lamda;
          break;
        default:
          throw new IllegalStateException();
      }
      canvas.rotate(lamda, bounds.width() / 2, bounds.height() / 2);
      canvas.translate(-bounds.width() / 3, bounds.height() / 3);
      canvas.drawRect(new RectF(0, 0, bounds.width() * 2,
          bounds.height() * 2), paint);
      canvas.restore();
    }

    @Override
    public void setAlpha(int alpha) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
      throw new UnsupportedOperationException();
    }

    @Override
    public int getOpacity() {
      return 0;
    }
  }

  public interface OnVoteListener {
    void vote(int vote);
  }
}
