// Copyright 2014 The Flutter 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 'dart:math';

import 'package:flutter/material.dart';

class CardModel {
  CardModel(this.value, this.height) : textController = TextEditingController(text: 'Item $value');

  int value;
  double height;
  int get color => ((value % 9) + 1) * 100;
  final TextEditingController textController;
  Key get key => ObjectKey(this);
}

class CardCollection extends StatefulWidget {
  const CardCollection({super.key});

  @override
  CardCollectionState createState() => CardCollectionState();
}

class CardCollectionState extends State<CardCollection> {
  static const TextStyle cardLabelStyle = TextStyle(
    color: Colors.white,
    fontSize: 18.0,
    fontWeight: FontWeight.bold,
  );

  // TODO(hansmuller): need a local image asset
  static const String _sunshineURL =
      'http://www.walltor.com/images/wallpaper/good-morning-sunshine-58540.jpg';

  static const double kCardMargins = 8.0;
  static const double kFixedCardHeight = 100.0;
  static const List<double> _cardHeights = <double>[
    48.0,
    63.0,
    85.0,
    146.0,
    60.0,
    55.0,
    84.0,
    96.0,
    50.0,
    48.0,
    63.0,
    85.0,
    146.0,
    60.0,
    55.0,
    84.0,
    96.0,
    50.0,
    48.0,
    63.0,
    85.0,
    146.0,
    60.0,
    55.0,
    84.0,
    96.0,
    50.0,
  ];

  MaterialColor _primaryColor = Colors.deepPurple;
  List<CardModel> _cardModels = <CardModel>[];
  DismissDirection _dismissDirection = DismissDirection.horizontal;
  TextAlign _textAlign = TextAlign.center;
  bool _editable = false;
  bool _fixedSizeCards = false;
  bool _sunshine = false;
  bool _varyFontSizes = false;

  void _updateCardSizes() {
    if (_fixedSizeCards) {
      return;
    }
    _cardModels = List<CardModel>.generate(_cardModels.length, (int i) {
      _cardModels[i].height = _editable ? max(_cardHeights[i], 60.0) : _cardHeights[i];
      return _cardModels[i];
    });
  }

  void _initVariableSizedCardModels() {
    _cardModels = List<CardModel>.generate(
      _cardHeights.length,
      (int i) => CardModel(i, _editable ? max(_cardHeights[i], 60.0) : _cardHeights[i]),
    );
  }

  void _initFixedSizedCardModels() {
    const cardCount = 27;
    _cardModels = List<CardModel>.generate(cardCount, (int i) => CardModel(i, kFixedCardHeight));
  }

  void _initCardModels() {
    if (_fixedSizeCards) {
      _initFixedSizedCardModels();
    } else {
      _initVariableSizedCardModels();
    }
  }

  @override
  void initState() {
    super.initState();
    _initCardModels();
  }

  void dismissCard(CardModel card) {
    if (_cardModels.contains(card)) {
      setState(() {
        _cardModels.remove(card);
      });
    }
  }

  Widget _buildDrawer() {
    return Drawer(
      child: IconTheme(
        data: const IconThemeData(color: Colors.black),
        child: ListView(
          children: <Widget>[
            const DrawerHeader(child: Center(child: Text('Options'))),
            buildDrawerCheckbox('Make card labels editable', _editable, _toggleEditable),
            buildDrawerCheckbox('Fixed size cards', _fixedSizeCards, _toggleFixedSizeCards),
            buildDrawerCheckbox('Let the sun shine', _sunshine, _toggleSunshine),
            buildDrawerCheckbox(
              'Vary font sizes',
              _varyFontSizes,
              _toggleVaryFontSizes,
              enabled: !_editable,
            ),
            const Divider(),
            buildDrawerColorRadioItem(
              'Deep Purple',
              Colors.deepPurple,
              _primaryColor,
              _selectColor,
            ),
            buildDrawerColorRadioItem('Green', Colors.green, _primaryColor, _selectColor),
            buildDrawerColorRadioItem('Amber', Colors.amber, _primaryColor, _selectColor),
            buildDrawerColorRadioItem('Teal', Colors.teal, _primaryColor, _selectColor),
            const Divider(),
            buildDrawerDirectionRadioItem(
              'Dismiss horizontally',
              DismissDirection.horizontal,
              _dismissDirection,
              _changeDismissDirection,
              icon: Icons.code,
            ),
            buildDrawerDirectionRadioItem(
              'Dismiss left',
              DismissDirection.endToStart,
              _dismissDirection,
              _changeDismissDirection,
              icon: Icons.arrow_back,
            ),
            buildDrawerDirectionRadioItem(
              'Dismiss right',
              DismissDirection.startToEnd,
              _dismissDirection,
              _changeDismissDirection,
              icon: Icons.arrow_forward,
            ),
            const Divider(),
            buildFontRadioItem(
              'Left-align text',
              TextAlign.left,
              _textAlign,
              _changeTextAlign,
              icon: Icons.format_align_left,
              enabled: !_editable,
            ),
            buildFontRadioItem(
              'Center-align text',
              TextAlign.center,
              _textAlign,
              _changeTextAlign,
              icon: Icons.format_align_center,
              enabled: !_editable,
            ),
            buildFontRadioItem(
              'Right-align text',
              TextAlign.right,
              _textAlign,
              _changeTextAlign,
              icon: Icons.format_align_right,
              enabled: !_editable,
            ),
            const Divider(),
            ListTile(
              leading: const Icon(Icons.dvr),
              onTap: () {
                debugDumpApp();
                debugDumpRenderTree();
              },
              title: const Text('Dump App to Console'),
            ),
          ],
        ),
      ),
    );
  }

  String _dismissDirectionText(DismissDirection direction) {
    final s = direction.toString();
    return "dismiss ${s.substring(s.indexOf('.') + 1)}";
  }

  void _toggleEditable() {
    setState(() {
      _editable = !_editable;
      _updateCardSizes();
    });
  }

  void _toggleFixedSizeCards() {
    setState(() {
      _fixedSizeCards = !_fixedSizeCards;
      _initCardModels();
    });
  }

  void _toggleSunshine() {
    setState(() {
      _sunshine = !_sunshine;
    });
  }

  void _toggleVaryFontSizes() {
    setState(() {
      _varyFontSizes = !_varyFontSizes;
    });
  }

  void _selectColor(MaterialColor? selection) {
    setState(() {
      _primaryColor = selection!;
    });
  }

  void _changeDismissDirection(DismissDirection? newDismissDirection) {
    setState(() {
      _dismissDirection = newDismissDirection!;
    });
  }

  void _changeTextAlign(TextAlign? newTextAlign) {
    setState(() {
      _textAlign = newTextAlign!;
    });
  }

  Widget buildDrawerCheckbox(
    String label,
    bool value,
    void Function() callback, {
    bool enabled = true,
  }) {
    return ListTile(
      onTap: enabled ? callback : null,
      title: Text(label),
      trailing: Checkbox(
        value: value,
        onChanged: enabled
            ? (_) {
                callback();
              }
            : null,
      ),
    );
  }

  Widget buildDrawerColorRadioItem(
    String label,
    MaterialColor itemValue,
    MaterialColor currentValue,
    ValueChanged<MaterialColor?> onChanged, {
    IconData? icon,
    bool enabled = true,
  }) {
    return ListTile(
      leading: Icon(icon),
      title: Text(label),
      onTap: enabled
          ? () {
              onChanged(itemValue);
            }
          : null,
      trailing: Radio<MaterialColor>(
        value: itemValue,
        groupValue: currentValue,
        onChanged: enabled ? onChanged : null,
      ),
    );
  }

  Widget buildDrawerDirectionRadioItem(
    String label,
    DismissDirection itemValue,
    DismissDirection currentValue,
    ValueChanged<DismissDirection?> onChanged, {
    IconData? icon,
    bool enabled = true,
  }) {
    return ListTile(
      leading: Icon(icon),
      title: Text(label),
      onTap: enabled
          ? () {
              onChanged(itemValue);
            }
          : null,
      trailing: Radio<DismissDirection>(
        value: itemValue,
        groupValue: currentValue,
        onChanged: enabled ? onChanged : null,
      ),
    );
  }

  Widget buildFontRadioItem(
    String label,
    TextAlign itemValue,
    TextAlign currentValue,
    ValueChanged<TextAlign?> onChanged, {
    IconData? icon,
    bool enabled = true,
  }) {
    return ListTile(
      leading: Icon(icon),
      title: Text(label),
      onTap: enabled
          ? () {
              onChanged(itemValue);
            }
          : null,
      trailing: Radio<TextAlign>(
        value: itemValue,
        groupValue: currentValue,
        onChanged: enabled ? onChanged : null,
      ),
    );
  }

  AppBar _buildAppBar(BuildContext context) {
    return AppBar(
      actions: <Widget>[Text(_dismissDirectionText(_dismissDirection))],
      flexibleSpace: Container(
        padding: const EdgeInsets.only(left: 72.0),
        height: 128.0,
        alignment: const Alignment(-1.0, 0.5),
        child: Text(
          'Swipe Away: ${_cardModels.length}',
          style: Theme.of(context).primaryTextTheme.titleLarge,
        ),
      ),
    );
  }

  Widget _buildCard(BuildContext context, int index) {
    final CardModel cardModel = _cardModels[index];
    final Widget card = Dismissible(
      key: ObjectKey(cardModel),
      direction: _dismissDirection,
      onDismissed: (DismissDirection direction) {
        dismissCard(cardModel);
      },
      child: Card(
        color: _primaryColor[cardModel.color],
        child: Container(
          height: cardModel.height,
          padding: const EdgeInsets.all(kCardMargins),
          child: _editable
              ? Center(
                  child: TextField(
                    key: GlobalObjectKey(cardModel),
                    controller: cardModel.textController,
                  ),
                )
              : DefaultTextStyle.merge(
                  style: cardLabelStyle.copyWith(fontSize: _varyFontSizes ? 5.0 + index : null),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[Text(cardModel.textController.text, textAlign: _textAlign)],
                  ),
                ),
        ),
      ),
    );

    String backgroundMessage;
    switch (_dismissDirection) {
      case DismissDirection.horizontal:
        backgroundMessage = 'Swipe in either direction';
      case DismissDirection.endToStart:
        backgroundMessage = 'Swipe left to dismiss';
      case DismissDirection.startToEnd:
        backgroundMessage = 'Swipe right to dismiss';
      case DismissDirection.vertical:
      case DismissDirection.up:
      case DismissDirection.down:
      case DismissDirection.none:
        backgroundMessage = 'Unsupported dismissDirection';
    }

    // This icon is wrong in RTL.
    Widget leftArrowIcon = const Icon(Icons.arrow_back, size: 36.0);
    if (_dismissDirection == DismissDirection.startToEnd) {
      leftArrowIcon = Opacity(opacity: 0.1, child: leftArrowIcon);
    }

    // This icon is wrong in RTL.
    Widget rightArrowIcon = const Icon(Icons.arrow_forward, size: 36.0);
    if (_dismissDirection == DismissDirection.endToStart) {
      rightArrowIcon = Opacity(opacity: 0.1, child: rightArrowIcon);
    }

    final ThemeData theme = Theme.of(context);
    final TextStyle? backgroundTextStyle = theme.primaryTextTheme.titleLarge;

    // The background Widget appears behind the Dismissible card when the card
    // moves to the left or right. The Positioned widget ensures that the
    // size of the background,card Stack will be based only on the card. The
    // Viewport ensures that when the card's resize animation occurs, the
    // background (text and icons) will just be clipped, not resized.
    final Widget background = Positioned.fill(
      child: Container(
        margin: const EdgeInsets.all(4.0),
        child: SingleChildScrollView(
          child: Container(
            height: cardModel.height,
            color: theme.primaryColor,
            child: Row(
              children: <Widget>[
                leftArrowIcon,
                Expanded(
                  child: Text(
                    backgroundMessage,
                    style: backgroundTextStyle,
                    textAlign: TextAlign.center,
                  ),
                ),
                rightArrowIcon,
              ],
            ),
          ),
        ),
      ),
    );

    return IconTheme(
      key: cardModel.key,
      data: const IconThemeData(color: Colors.white),
      child: Stack(children: <Widget>[background, card]),
    );
  }

  Shader _createShader(Rect bounds) {
    return const LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: <Color>[Color(0x00FFFFFF), Color(0xFFFFFFFF)],
      stops: <double>[0.1, 0.35],
    ).createShader(bounds);
  }

  @override
  Widget build(BuildContext context) {
    Widget cardCollection = ListView.builder(
      itemExtent: _fixedSizeCards ? kFixedCardHeight : null,
      itemCount: _cardModels.length,
      itemBuilder: _buildCard,
    );

    if (_sunshine) {
      cardCollection = Stack(
        children: <Widget>[
          Column(children: <Widget>[Image.network(_sunshineURL)]),
          ShaderMask(shaderCallback: _createShader, child: cardCollection),
        ],
      );
    }

    final Widget body = Container(
      padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
      color: _primaryColor.shade50,
      child: cardCollection,
    );

    return Theme(
      data: ThemeData(primarySwatch: _primaryColor),
      child: Scaffold(appBar: _buildAppBar(context), drawer: _buildDrawer(), body: body),
    );
  }
}

void main() {
  runApp(const MaterialApp(title: 'Cards', home: CardCollection()));
}
