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

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';

abstract class _KeyboardKey extends StatelessWidget {
  const _KeyboardKey({
    @required this.height,
    @required this.onTap,
    this.onLongPress,
    this.flex = 2,
    Key key,
  }) : super(key: key);

  /// The size of the key relative to its siblings.
  final int flex;

  /// The height of the key.
  final double height;

  /// Called when the key is pressed.
  final Function onTap;

  /// Called when the key is long-pressed.
  final VoidCallback onLongPress;
}

/// Called when a key is pressed.
typedef OnText = void Function(String text);

/// A spacer that is inserted into the keyboard to provide empty space
/// between other keys in the keyboard.
///
/// The [SpacerKey] is expected to have a [Row] as a parent.
///
/// Note: No state is required but necessary in order to subclass [_KeyboardKey].
class SpacerKey extends _KeyboardKey {
  const SpacerKey({
    GlobalKey key,
    int flex,
  }) : super(key: key, height: 0.0, flex: flex, onTap: null);

  @override
  Widget build(BuildContext context) => Spacer(flex: flex, key: key);
}

/// A key that is represented by a string.
///
/// The [TextKey] is expected to have a [Row] as a parent and an ancestor
/// [Material] widget
class TextKey extends _KeyboardKey {
  const TextKey(
    this.text, {
    @required double height,
    GlobalKey key,
    OnText onText,
    this.style,
    this.verticalAlign = 0.5,
    this.horizontalAlign = 0.5,
    int flex,
  }) : super(key: key, height: height, flex: flex, onTap: onText);

  /// The text to display.
  final String text;

  /// The style of the text.
  final TextStyle style;

  /// The vertical alignment the text should have within its container.
  final double verticalAlign;

  /// The horizontal alignment the text should have within its container.
  final double horizontalAlign;

  @override
  Widget build(BuildContext context) {
    debugCheckHasMaterial(context);
    _debugCheckHasRow(context);
    return Expanded(
      flex: flex,
      child: InkWell(
        child: Container(
          height: height,
          child: Align(
            alignment: FractionalOffset(horizontalAlign, verticalAlign),
            child: Text(text, style: style),
          ),
        ),
        onTap: () => onTap?.call(text),
        onLongPress: onLongPress,
      ),
    );
  }
}

enum IconKeyType {
  normal,
  bordered,
  dark,
}

/// A key that is represented by an icon.
///
/// The [IconKey] is expected to have a [Row] as a parent and an ancestor
/// [Material] widget
class IconKey extends _KeyboardKey {
  const IconKey({
    @required this.iconData,
    @required this.iconColor,
    @required double height,
    this.type = IconKeyType.normal,
    this.accentColor = Colors.transparent,
    VoidCallback onKeyPressed,
    int flex,
    Key key,
  }) : super(height: height, flex: flex, key: key, onTap: onKeyPressed);

  static const double _padding = 4.0;

  static const double _borderWidth = 2.0;

  /// The [IconData] of the key
  final IconData iconData;

  final IconKeyType type;

  /// The color filter to apply to the icon in the key.
  final Color iconColor;

  /// The color filter to the background or border if [type] is
  /// not [IconKeyType.normal].
  final Color accentColor;

  @override
  Widget build(BuildContext context) {
    debugCheckHasMaterial(context);
    _debugCheckHasRow(context);

    final shape = CircleBorder(
        side: type == IconKeyType.bordered
            ? BorderSide(color: accentColor, width: _borderWidth)
            : BorderSide.none);
    final backgroundColor =
        type == IconKeyType.dark ? accentColor : Colors.transparent;
    final padding = type == IconKeyType.dark ? _padding : 0.0;

    return Expanded(
      flex: flex,
      child: Container(
        padding: EdgeInsets.all(padding),
        height: height,
        child: Container(
          decoration: ShapeDecoration(
            color: backgroundColor,
            shape: shape,
          ),
          child: InkWell(
            customBorder: type == IconKeyType.normal ? null : shape,
            child: Icon(iconData, color: iconColor),
            onTap: onTap ?? () {},
            onLongPress: onLongPress,
          ),
        ),
      ),
    );
  }
}

/// A key that is representative of the space bar.
///
/// The [SpaceBarKey] is expected to have a [Row] as a parent and an ancestor
/// [Material] widget
class SpaceBarKey extends _KeyboardKey {
  const SpaceBarKey({
    @required this.accentColor,
    @required double height,
    VoidCallback onTap,
    int flex,
    Key key,
  }) : super(key: key, height: height, flex: flex, onTap: onTap);

  /// The color filter to apply to the icon in the key.
  final Color accentColor;

  @override
  Widget build(BuildContext context) {
    debugCheckHasMaterial(context);
    _debugCheckHasRow(context);
    return Expanded(
      flex: flex,
      child: InkWell(
        child: Container(
          height: height,
          child: FractionallySizedBox(
            widthFactor: 0.9,
            heightFactor: 0.2,
            child: Container(
              decoration: ShapeDecoration(
                color: accentColor,
                shape: StadiumBorder(side: BorderSide.none),
              ),
            ),
          ),
        ),
        onTap: onTap ?? () {},
        onLongPress: onLongPress,
      ),
    );
  }
}

bool _debugCheckHasRow(BuildContext context) {
  assert(
      context.widget is Row || context.ancestorWidgetOfExactType(Row) != null,
      '${context.widget.runtimeType} widgets require a Row widget ancestor.');
  return true;
}
