// 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.util;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.StringRes;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TableRow;
import android.widget.TextView;

import com.google.gerrit.extensions.common.AccountInfo;
import com.google.reviewit.AvatarTask;
import com.google.reviewit.R;
import com.google.reviewit.app.ReviewItApp;

import static com.google.reviewit.util.LayoutUtil.wrapTableRowLayout;

public class WidgetUtil {
  private final Context context;

  public WidgetUtil(Context context) {
    this.context = context;
  }

  public
  @ColorInt
  int color(@ColorRes int id) {
    // TODO use getResources().getColor(id, null) with API 23
    return context.getResources().getColor(id);
  }

  public int spToPx(int sp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
        context.getResources().getDisplayMetrics());
  }

  public int dpToPx(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
        context.getResources().getDisplayMetrics());
  }

  public Drawable getDrawable(@DrawableRes int id) {
    return context.getResources().getDrawable(id);
  }

  public View tableRowRightMargin(View view, int rightMarginDp) {
    TableRow.LayoutParams layoutParams =
        (TableRow.LayoutParams) view.getLayoutParams();
    layoutParams.rightMargin = dpToPx(rightMarginDp);
    view.setLayoutParams(layoutParams);
    return view;
  }

  public TextView createTextView(String text, int textSizeSp) {
    return createTextView(text, textSizeSp, false);
  }

  public TextView createTextView(String text, int textSizeSp, boolean isHtlm) {
    TextView textView = new TextView(context);
    textView.setLayoutParams(wrapTableRowLayout());
    textView.setText(isHtlm ? Html.fromHtml(text) : text);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSp);
    if (isHtlm) {
      textView.setLinkTextColor(color(R.color.hyperlink));
      textView.setMovementMethod(LinkMovementMethod.getInstance());
    }
    return textView;
  }

  public static void underline(TextView textView) {
    textView.setPaintFlags(textView.getPaintFlags()
        | Paint.UNDERLINE_TEXT_FLAG);
  }

  public void showError(@StringRes int id) {
    showError(context.getString(id));
  }

  public void showError(String msg) {
    new AlertDialog.Builder(context)
        .setTitle(context.getString(R.string.error_title))
        .setMessage(msg)
        .setPositiveButton(android.R.string.ok,
            new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            // do nothing
          }
        }).setIcon(android.R.drawable.ic_dialog_alert).show();
  }

  public int getDimension(@DimenRes int id) {
    return (int) context.getResources().getDimension(id);
  }

  public void setBackgroundColor(View view, @ColorRes int colorId) {
    view.setBackgroundColor(color(colorId));
  }

  public static void setBackground(View view, Drawable drawable) {
    // TODO use setBackGround(Drawable) with API 16
    view.setBackgroundDrawable(drawable);
  }

  public static void setXY(View view, int x, int y) {
    view.setX(x);
    view.setY(y);
  }

  public static void setRightMargin(View view, int margin) {
    ViewGroup.MarginLayoutParams layoutParams =
        (ViewGroup.MarginLayoutParams) view.getLayoutParams();
    layoutParams.rightMargin = margin;
  }

  public static View setBottomMargin(View view, int margin) {
    ViewGroup.MarginLayoutParams layoutParams =
        (ViewGroup.MarginLayoutParams) view.getLayoutParams();
    layoutParams.bottomMargin = margin;
    return view;
  }

  public static void setText(View view, String text) {
    if (view instanceof TextView) {
      ((TextView) view).setText(text);
    } else {
      throw new IllegalStateException("unexpected view type "
          + view.getClass().getName() + " for id " + view.getId());
    }
  }

  public static void setText(View base, @IdRes int id, String text) {
    View view = base.findViewById(id);
    if (view instanceof TextView) {
      ((TextView) view).setText(text);
    } else {
      throw new IllegalStateException("unexpected view type "
          + view.getClass().getName() + " for id " + id);
    }
  }

  public static void displayAvatar(
      ReviewItApp app, AccountInfo account, ImageView avatar) {
    new AvatarTask(app, avatar).executeOnExecutor(app.getExecutor(), account);
  }

  public static void setGone(View... views) {
    for (View view : views) {
      view.setVisibility(View.GONE);
    }
  }

  public static void setInvisible(View... views) {
    for (View view : views) {
      view.setVisibility(View.INVISIBLE);
    }
  }

  public static void setVisible(View... views) {
    for (View view : views) {
      view.setVisibility(View.VISIBLE);
    }
  }

  public static void setVisible(boolean visible, View... views) {
    if (visible) {
      setVisible(views);
    } else {
      setGone(views);
    }
  }
}
