// 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 'package:flutter/material.dart';

class CardModel {
  CardModel(this.value, this.size, this.color);
  int value;
  Size size;
  Color color;
  String get label => 'Card $value';
  Key get key => ObjectKey(this);
}

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

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

class PageViewAppState extends State<PageViewApp> {
  @override
  void initState() {
    super.initState();
    const List<Size> cardSizes = <Size>[
      Size(100.0, 300.0),
      Size(300.0, 100.0),
      Size(200.0, 400.0),
      Size(400.0, 400.0),
      Size(300.0, 400.0),
    ];

    cardModels = List<CardModel>.generate(cardSizes.length, (int i) {
      final Color? color = Color.lerp(
        Colors.red.shade300,
        Colors.blue.shade900,
        i / cardSizes.length,
      );
      return CardModel(i, cardSizes[i], color!);
    });
  }

  static const TextStyle cardLabelStyle = TextStyle(
    color: Colors.white,
    fontSize: 18.0,
    fontWeight: FontWeight.bold,
  );

  List<CardModel> cardModels = <CardModel>[];
  Size pageSize = const Size(200.0, 200.0);
  Axis scrollDirection = Axis.horizontal;
  bool itemsWrap = false;

  Widget buildCard(CardModel cardModel) {
    final Widget card = Card(
      color: cardModel.color,
      child: Container(
        width: cardModel.size.width,
        height: cardModel.size.height,
        padding: const EdgeInsets.all(8.0),
        child: Center(child: Text(cardModel.label, style: cardLabelStyle)),
      ),
    );

    final BoxConstraints constraints = (scrollDirection == Axis.vertical)
        ? BoxConstraints.tightFor(height: pageSize.height)
        : BoxConstraints.tightFor(width: pageSize.width);

    return Container(
      key: cardModel.key,
      constraints: constraints,
      child: Center(child: card),
    );
  }

  void switchScrollDirection() {
    setState(() {
      scrollDirection = flipAxis(scrollDirection);
    });
  }

  void toggleItemsWrap() {
    setState(() {
      itemsWrap = !itemsWrap;
    });
  }

  Widget _buildDrawer() {
    return Drawer(
      child: ListView(
        children: <Widget>[
          const DrawerHeader(child: Center(child: Text('Options'))),
          ListTile(
            leading: const Icon(Icons.more_horiz),
            selected: scrollDirection == Axis.horizontal,
            trailing: const Text('Horizontal Layout'),
            onTap: switchScrollDirection,
          ),
          ListTile(
            leading: const Icon(Icons.more_vert),
            selected: scrollDirection == Axis.vertical,
            trailing: const Text('Vertical Layout'),
            onTap: switchScrollDirection,
          ),
          ListTile(
            onTap: toggleItemsWrap,
            title: const Text('Scrolling wraps around'),
            // TODO(abarth): Actually make this checkbox change this value.
            trailing: Checkbox(value: itemsWrap, onChanged: null),
          ),
        ],
      ),
    );
  }

  AppBar _buildAppBar() {
    return AppBar(title: const Text('PageView'), actions: <Widget>[Text(scrollDirection.name)]);
  }

  Widget _buildBody(BuildContext context) {
    return PageView(
      // TODO(abarth): itemsWrap: itemsWrap,
      scrollDirection: scrollDirection,
      children: cardModels.map<Widget>(buildCard).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return IconTheme(
      data: const IconThemeData(color: Colors.white),
      child: Scaffold(appBar: _buildAppBar(), drawer: _buildDrawer(), body: _buildBody(context)),
    );
  }
}

void main() {
  runApp(const MaterialApp(title: 'PageView', home: PageViewApp()));
}
