/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.views.toolbar;

import javax.annotation.Nullable;

import java.util.Map;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.LayoutDirection;
import android.view.MenuItem;
import android.view.View;

import com.facebook.react.R;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.SystemClock;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.toolbar.events.ToolbarClickEvent;

/**
 * Manages instances of ReactToolbar.
 */
public class ReactToolbarManager extends ViewGroupManager<ReactToolbar> {

  private static final String REACT_CLASS = "ToolbarAndroid";

  @Override
  public String getName() {
    return REACT_CLASS;
  }

  @Override
  protected ReactToolbar createViewInstance(ThemedReactContext reactContext) {
    return new ReactToolbar(reactContext);
  }

  @ReactProp(name = "logo")
  public void setLogo(ReactToolbar view, @Nullable ReadableMap logo) {
    view.setLogoSource(logo);
  }

  @ReactProp(name = "navIcon")
  public void setNavIcon(ReactToolbar view, @Nullable ReadableMap navIcon) {
    view.setNavIconSource(navIcon);
  }

  @ReactProp(name = "overflowIcon")
  public void setOverflowIcon(ReactToolbar view, @Nullable ReadableMap overflowIcon) {
    view.setOverflowIconSource(overflowIcon);
  }

  @ReactProp(name = "rtl")
  public void setRtl(ReactToolbar view, boolean rtl) {
    view.setLayoutDirection(rtl ? LayoutDirection.LTR : LayoutDirection.RTL);
  }

  @ReactProp(name = "subtitle")
  public void setSubtitle(ReactToolbar view, @Nullable String subtitle) {
    view.setSubtitle(subtitle);
  }

  @ReactProp(name = "subtitleColor", customType = "Color")
  public void setSubtitleColor(ReactToolbar view, @Nullable Integer subtitleColor) {
    int[] defaultColors = getDefaultColors(view.getContext());
    if (subtitleColor != null) {
      view.setSubtitleTextColor(subtitleColor);
    } else {
      view.setSubtitleTextColor(defaultColors[1]);
    }
  }

  @ReactProp(name = "title")
  public void setTitle(ReactToolbar view, @Nullable String title) {
    view.setTitle(title);
  }

  @ReactProp(name = "titleColor", customType = "Color")
  public void setTitleColor(ReactToolbar view, @Nullable Integer titleColor) {
    int[] defaultColors = getDefaultColors(view.getContext());
    if (titleColor != null) {
      view.setTitleTextColor(titleColor);
    } else {
      view.setTitleTextColor(defaultColors[0]);
    }
  }

  @ReactProp(name = "contentInsetStart", defaultFloat = Float.NaN)
  public void setContentInsetStart(ReactToolbar view, float insetStart) {
    int inset = Float.isNaN(insetStart) ?
        getDefaultContentInsets(view.getContext())[0] :
        Math.round(PixelUtil.toPixelFromDIP(insetStart));
    view.setContentInsetsRelative(inset, view.getContentInsetEnd());
  }

  @ReactProp(name = "contentInsetEnd", defaultFloat = Float.NaN)
  public void setContentInsetEnd(ReactToolbar view, float insetEnd) {
    int inset = Float.isNaN(insetEnd) ?
        getDefaultContentInsets(view.getContext())[1] :
        Math.round(PixelUtil.toPixelFromDIP(insetEnd));
    view.setContentInsetsRelative(view.getContentInsetStart(), inset);
  }

  @ReactProp(name = "nativeActions")
  public void setActions(ReactToolbar view, @Nullable ReadableArray actions) {
    view.setActions(actions);
  }

  @Override
  protected void addEventEmitters(final ThemedReactContext reactContext, final ReactToolbar view) {
    final EventDispatcher mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class)
        .getEventDispatcher();
    view.setNavigationOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            mEventDispatcher.dispatchEvent(
                new ToolbarClickEvent(view.getId(), SystemClock.nanoTime(), -1));
          }
        });

    view.setOnMenuItemClickListener(
        new ReactToolbar.OnMenuItemClickListener() {
          @Override
          public boolean onMenuItemClick(MenuItem menuItem) {
            mEventDispatcher.dispatchEvent(
                new ToolbarClickEvent(
                    view.getId(),
                    SystemClock.nanoTime(),
                    menuItem.getOrder()));
            return true;
          }
        });
  }

  @Nullable
  @Override
  public Map<String, Object> getExportedViewConstants() {
    return MapBuilder.<String, Object>of(
        "ShowAsAction",
        MapBuilder.of(
            "never", MenuItem.SHOW_AS_ACTION_NEVER,
            "always", MenuItem.SHOW_AS_ACTION_ALWAYS,
            "ifRoom", MenuItem.SHOW_AS_ACTION_IF_ROOM));
  }

  @Override
  public boolean needsCustomLayoutForChildren() {
    return true;
  }

  private int[] getDefaultContentInsets(Context context) {
    Resources.Theme theme = context.getTheme();
    TypedArray toolbarStyle = null;
    TypedArray contentInsets = null;

    try {
      toolbarStyle = theme
              .obtainStyledAttributes(new int[]{R.attr.toolbarStyle});

      int toolbarStyleResId = toolbarStyle.getResourceId(0, 0);

      contentInsets = theme.obtainStyledAttributes(
              toolbarStyleResId, new int[]{
                      R.attr.contentInsetStart,
                      R.attr.contentInsetEnd,
              });

      int contentInsetStart = contentInsets.getDimensionPixelSize(0, 0);
      int contentInsetEnd = contentInsets.getDimensionPixelSize(1, 0);

      return new int[] {contentInsetStart, contentInsetEnd};
    } finally {
      recycleQuietly(toolbarStyle);
      recycleQuietly(contentInsets);
    }

  }

  private static int[] getDefaultColors(Context context) {
    Resources.Theme theme = context.getTheme();
    TypedArray toolbarStyle = null;
    TypedArray textAppearances = null;
    TypedArray titleTextAppearance = null;
    TypedArray subtitleTextAppearance = null;

    try {
      toolbarStyle = theme
          .obtainStyledAttributes(new int[]{R.attr.toolbarStyle});
      int toolbarStyleResId = toolbarStyle.getResourceId(0, 0);
      textAppearances = theme.obtainStyledAttributes(
          toolbarStyleResId, new int[]{
              R.attr.titleTextAppearance,
              R.attr.subtitleTextAppearance,
          });
      int titleTextAppearanceResId = textAppearances.getResourceId(0, 0);
      int subtitleTextAppearanceResId = textAppearances.getResourceId(1, 0);

      titleTextAppearance = theme
          .obtainStyledAttributes(titleTextAppearanceResId, new int[]{android.R.attr.textColor});
      subtitleTextAppearance = theme
          .obtainStyledAttributes(subtitleTextAppearanceResId, new int[]{android.R.attr.textColor});

      int titleTextColor = titleTextAppearance.getColor(0, Color.BLACK);
      int subtitleTextColor = subtitleTextAppearance.getColor(0, Color.BLACK);

      return new int[] {titleTextColor, subtitleTextColor};
    } finally {
      recycleQuietly(toolbarStyle);
      recycleQuietly(textAppearances);
      recycleQuietly(titleTextAppearance);
      recycleQuietly(subtitleTextAppearance);
    }
  }

  private static void recycleQuietly(@Nullable TypedArray style) {
    if (style != null) {
      style.recycle();
    }
  }

}
