// Copyright 2021 Google LLC
//
// 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.

// This file is automatically generated. Do not modify it.

import 'dart:math';

import '../hct/cam16.dart';
import '../hct/hct.dart';
import '../utils/color_utils.dart';
import '../utils/math_utils.dart';

/// Functions for blending in HCT and CAM16.
class Blend {
  /// Blend the design color's HCT hue towards the key color's HCT
  /// hue, in a way that leaves the original color recognizable and
  /// recognizably shifted towards the key color.
  ///
  /// [designColor] ARGB representation of an arbitrary color.
  /// [sourceColor] ARGB representation of the main theme color.
  /// Returns The design color with a hue shifted towards the
  /// system's color, a slightly warmer/cooler variant of the design
  /// color's hue.
  static int harmonize(int designColor, int sourceColor) {
    final fromHct = Hct.fromInt(designColor);
    final toHct = Hct.fromInt(sourceColor);
    final differenceDegrees = MathUtils.differenceDegrees(
      fromHct.hue,
      toHct.hue,
    );
    final rotationDegrees = min(differenceDegrees * 0.5, 15.0);
    final outputHue = MathUtils.sanitizeDegreesDouble(
      fromHct.hue +
          rotationDegrees * MathUtils.rotationDirection(fromHct.hue, toHct.hue),
    );
    return Hct.from(outputHue, fromHct.chroma, fromHct.tone).toInt();
  }

  /// Blends hue from one color into another. The chroma and tone of
  /// the original color are maintained.
  ///
  /// [from] ARGB representation of color
  /// [to] ARGB representation of color
  /// [amount] how much blending to perform; 0.0 >= and <= 1.0
  /// Returns from, with a hue blended towards to. Chroma and tone
  /// are constant.
  static int hctHue(int from, int to, double amount) {
    final ucs = cam16Ucs(from, to, amount);
    final ucsCam = Cam16.fromInt(ucs);
    final fromCam = Cam16.fromInt(from);
    final blended = Hct.from(
      ucsCam.hue,
      fromCam.chroma,
      ColorUtils.lstarFromArgb(from),
    );
    return blended.toInt();
  }

  /// Blend in CAM16-UCS space.
  ///
  /// [from] ARGB representation of color
  /// [to] ARGB representation of color
  /// [amount] how much blending to perform; 0.0 >= and <= 1.0
  /// Returns from, blended towards to. Hue, chroma, and tone will
  /// change.
  static int cam16Ucs(int from, int to, double amount) {
    final fromCam = Cam16.fromInt(from);
    final toCam = Cam16.fromInt(to);
    final fromJ = fromCam.jstar;
    final fromA = fromCam.astar;
    final fromB = fromCam.bstar;
    final toJ = toCam.jstar;
    final toA = toCam.astar;
    final toB = toCam.bstar;
    final jstar = fromJ + (toJ - fromJ) * amount;
    final astar = fromA + (toA - fromA) * amount;
    final bstar = fromB + (toB - fromB) * amount;
    return Cam16.fromUcs(jstar, astar, bstar).toInt();
  }
}
