// 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 int 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 String 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';
        break;
      case DismissDirection.endToStart:
        backgroundMessage = 'Swipe left to dismiss';
        break;
      case DismissDirection.startToEnd:
        backgroundMessage = 'Swipe right to dismiss';
        break;
      case DismissDirection.vertical:
      case DismissDirection.up:
      case DismissDirection.down:
      case DismissDirection.none:
        backgroundMessage = 'Unsupported dismissDirection';
        break;
    }

    // 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(),
  ));
}
