// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include <cmath>
#include <cstdlib>
#include <string>

#include "starboard/accessibility.h"
#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/android/shared/jni_utils.h"
#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/accessibility_internal.h"

using starboard::android::shared::JniEnvExt;
using starboard::android::shared::ScopedLocalJavaRef;
using starboard::shared::starboard::GetClosestCaptionColor;
using starboard::shared::starboard::GetClosestFontSizePercentage;
using starboard::shared::starboard::GetClosestOpacity;

namespace {

SbAccessibilityCaptionCharacterEdgeStyle AndroidEdgeTypeToSbEdgeStyle(
    int edge_type) {
  switch (edge_type) {
    case 0:
      return kSbAccessibilityCaptionCharacterEdgeStyleNone;
    case 1:
      return kSbAccessibilityCaptionCharacterEdgeStyleUniform;
    case 2:
      return kSbAccessibilityCaptionCharacterEdgeStyleDropShadow;
    case 3:
      return kSbAccessibilityCaptionCharacterEdgeStyleRaised;
    case 4:
      return kSbAccessibilityCaptionCharacterEdgeStyleDepressed;
    default:
      SB_NOTREACHED() << "Invalid edge type conversion";
      return kSbAccessibilityCaptionCharacterEdgeStyleNone;
  }
}

SbAccessibilityCaptionFontFamily AndroidFontFamilyToSbFontFamily(int family) {
  switch (family) {
    case 0:
      return kSbAccessibilityCaptionFontFamilyCasual;
    case 1:
      return kSbAccessibilityCaptionFontFamilyCursive;
    case 2:
      return kSbAccessibilityCaptionFontFamilyMonospaceSansSerif;
    case 3:
      return kSbAccessibilityCaptionFontFamilyMonospaceSerif;
    case 4:
      return kSbAccessibilityCaptionFontFamilyProportionalSansSerif;
    case 5:
      return kSbAccessibilityCaptionFontFamilyProportionalSerif;
    case 6:
      return kSbAccessibilityCaptionFontFamilySmallCapitals;
    default:
      SB_NOTREACHED() << "Invalid font family conversion";
      return kSbAccessibilityCaptionFontFamilyCasual;
  }
}

SbAccessibilityCaptionState BooleanToCaptionState(bool is_set) {
  if (is_set) {
    return kSbAccessibilityCaptionStateSet;
  } else {
    return kSbAccessibilityCaptionStateUnset;
  }
}

void SetColorProperties(jobject j_caption_settings,
                        const char* color_field,
                        const char* has_color_field,
                        SbAccessibilityCaptionColor* color,
                        SbAccessibilityCaptionState* color_state,
                        SbAccessibilityCaptionOpacityPercentage* opacity,
                        SbAccessibilityCaptionState* opacity_state) {
  JniEnvExt* env = JniEnvExt::Get();
  jint j_color = env->GetIntFieldOrAbort(j_caption_settings, color_field, "I");
  *color = GetClosestCaptionColor(j_color);
  *opacity = GetClosestOpacity((0xFF & (j_color >> 24)) * 100 / 255);
  *color_state = BooleanToCaptionState(
      env->GetBooleanFieldOrAbort(j_caption_settings, has_color_field, "Z"));
  // Color and opacity are combined into a single ARGB value.
  // Therefore, if the color is set, so is the opacity.
  *opacity_state = *color_state;
}

}  // namespace

bool SbAccessibilityGetCaptionSettings(
    SbAccessibilityCaptionSettings* caption_settings) {
  if (!caption_settings ||
      !SbMemoryIsZero(caption_settings,
                      sizeof(SbAccessibilityCaptionSettings))) {
    return false;
  }

  JniEnvExt* env = JniEnvExt::Get();

  ScopedLocalJavaRef<jobject> j_caption_settings(
      env->CallStarboardObjectMethodOrAbort(
          "getCaptionSettings", "()Ldev/cobalt/media/CaptionSettings;"));

  jfloat font_scale =
      env->GetFloatFieldOrAbort(j_caption_settings.Get(), "fontScale", "F");
  caption_settings->font_size =
      GetClosestFontSizePercentage(100.0 * font_scale);
  // Android's captioning API always returns a font scale of 1 (100%) if
  // the font size has not been set. This means we have no way to check if
  // font size is "set" vs. "unset", so we'll just return "set" every time.
  caption_settings->font_size_state = kSbAccessibilityCaptionStateSet;

  // TODO: Convert Android typeface to font family.
  caption_settings->font_family = kSbAccessibilityCaptionFontFamilyCasual;
  caption_settings->font_family_state = kSbAccessibilityCaptionStateUnsupported;

  caption_settings->character_edge_style = AndroidEdgeTypeToSbEdgeStyle(
      env->GetIntFieldOrAbort(j_caption_settings.Get(), "edgeType", "I"));
  caption_settings->character_edge_style_state =
      BooleanToCaptionState(env->GetBooleanFieldOrAbort(
          j_caption_settings.Get(), "hasEdgeType", "Z"));

  SetColorProperties(
      j_caption_settings.Get(), "foregroundColor", "hasForegroundColor",
      &caption_settings->font_color, &caption_settings->font_color_state,
      &caption_settings->font_opacity, &caption_settings->font_opacity_state);

  SetColorProperties(j_caption_settings.Get(), "backgroundColor",
                     "hasBackgroundColor", &caption_settings->background_color,
                     &caption_settings->background_color_state,
                     &caption_settings->background_opacity,
                     &caption_settings->background_opacity_state);

  SetColorProperties(j_caption_settings.Get(), "windowColor", "hasWindowColor",
                     &caption_settings->window_color,
                     &caption_settings->window_color_state,
                     &caption_settings->window_opacity,
                     &caption_settings->window_opacity_state);

  caption_settings->is_enabled =
      env->GetBooleanFieldOrAbort(j_caption_settings.Get(), "isEnabled", "Z");
  caption_settings->supports_is_enabled = true;
  caption_settings->supports_set_enabled = false;

  return true;
}
