// Copyright 2019 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math';
import 'package:flutter/material.dart';

// Color gradients.
const pinkLeft = Color(0xFFFF5983);
const pinkRight = Color(0xFFFF8383);

const tealLeft = Color(0xFF1CDDC8);
const tealRight = Color(0xFF00A5B3);

// Dimensions.
const unitHeight = 1;
const unitWidth = 1;

const stickLength = 5 / 9;
const stickWidth = 5 / 36;
const stickRadius = stickWidth / 2;
const knobDiameter = 5 / 54;
const knobRadius = knobDiameter / 2;
const stickGap = 5 / 54;

// Locations.
const knobDistanceFromCenter = stickGap / 2 + stickWidth / 2;
const lowerKnobCenter = Offset(0, knobDistanceFromCenter);
const upperKnobCenter = Offset(0, -knobDistanceFromCenter);

const knobDeviation = stickLength / 2 - stickRadius;

// Key moments in animation.
const _colorKnobContractionBegins = 1 / 23;
const _monoKnobExpansionEnds = 11 / 23;
const _colorKnobContractionEnds = 14 / 23;

// Stages.
bool isTransitionPhase(double time) => time < _colorKnobContractionEnds;

// Curve easing.
const _curve = Curves.easeInOutCubic;

double _progress(
  double time, {
  @required double begin,
  @required double end,
}) =>
    _curve.transform(((time - begin) / (end - begin)).clamp(0, 1).toDouble());

double _monoKnobProgress(double time) => _progress(
      time,
      begin: 0,
      end: _monoKnobExpansionEnds,
    );

double _colorKnobProgress(double time) => _progress(
      time,
      begin: _colorKnobContractionBegins,
      end: _colorKnobContractionEnds,
    );

double _rotationProgress(double time) => _progress(
      time,
      begin: _colorKnobContractionEnds,
      end: 1,
    );

// Changing lengths: mono.
double monoLength(double time) =>
    _monoKnobProgress(time) * (stickLength - knobDiameter) + knobDiameter;

double _monoLengthLeft(double time) =>
    min(monoLength(time) - knobRadius, stickRadius);

double _monoLengthRight(double time) =>
    monoLength(time) - _monoLengthLeft(time);

double _monoHorizontalOffset(double time) =>
    (_monoLengthRight(time) - _monoLengthLeft(time)) / 2 - knobDeviation;

Offset upperMonoOffset(double time) =>
    upperKnobCenter + Offset(_monoHorizontalOffset(time), 0);

Offset lowerMonoOffset(double time) =>
    lowerKnobCenter + Offset(-_monoHorizontalOffset(time), 0);

// Changing lengths: color.
double colorLength(double time) => (1 - _colorKnobProgress(time)) * stickLength;

Offset upperColorOffset(double time) =>
    upperKnobCenter + Offset(stickLength / 2 - colorLength(time) / 2, 0);

Offset lowerColorOffset(double time) =>
    lowerKnobCenter + Offset(-stickLength / 2 + colorLength(time) / 2, 0);

// Moving objects.
double knobRotation(double time) => _rotationProgress(time) * pi / 4;

Offset knobCenter(double time) {
  final progress = _rotationProgress(time);
  if (progress == 0) {
    return lowerKnobCenter;
  } else if (progress == 1) {
    return upperKnobCenter;
  } else {
    // Calculates the current location.
    final center = Offset(knobDistanceFromCenter / tan(pi / 8), 0);
    final radius = (lowerKnobCenter - center).distance;
    final angle = pi + (progress - 1 / 2) * pi / 4;
    return center + Offset.fromDirection(angle, radius);
  }
}
