// 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';
import 'package:flutter/scheduler.dart' show timeDilation;

void main() {
  runApp(
    const ComplexLayoutApp()
  );
}

enum ScrollMode { complex, tile }

class ComplexLayoutApp extends StatefulWidget {
  const ComplexLayoutApp({Key? key}) : super(key: key);

  @override
  ComplexLayoutAppState createState() => ComplexLayoutAppState();

  static ComplexLayoutAppState? of(BuildContext context) => context.findAncestorStateOfType<ComplexLayoutAppState>();
}

class ComplexLayoutAppState extends State<ComplexLayoutApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: lightTheme ? ThemeData.light() : ThemeData.dark(),
      title: 'Advanced Layout',
      home: scrollMode == ScrollMode.complex ? const ComplexLayout() : const TileScrollLayout());
  }

  bool _lightTheme = true;
  bool get lightTheme => _lightTheme;
  set lightTheme(bool value) {
    setState(() {
      _lightTheme = value;
    });
  }

  ScrollMode _scrollMode = ScrollMode.complex;
  ScrollMode get scrollMode => _scrollMode;
  set scrollMode(ScrollMode mode) {
    setState(() {
      _scrollMode = mode;
    });
  }

  void toggleAnimationSpeed() {
    setState(() {
      timeDilation = (timeDilation != 1.0) ? 1.0 : 5.0;
    });
  }
}

class TileScrollLayout extends StatelessWidget {
  const TileScrollLayout({ Key? key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Tile Scrolling Layout')),
      body: ListView.builder(
        key: const Key('tiles-scroll'),
        itemCount: 200,
        itemBuilder: (BuildContext context, int index) {
          return Padding(
            padding: const EdgeInsets.all(5.0),
            child: Material(
              elevation: (index % 5 + 1).toDouble(),
              color: Colors.white,
              child: const IconBar(),
            ),
          );
        },
      ),
      drawer: const GalleryDrawer(),
    );
  }
}

class ComplexLayout extends StatefulWidget {
  const ComplexLayout({ Key? key }) : super(key: key);

  @override
  ComplexLayoutState createState() => ComplexLayoutState();

  static ComplexLayoutState? of(BuildContext context) => context.findAncestorStateOfType<ComplexLayoutState>();
}

class ComplexLayoutState extends State<ComplexLayout> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Advanced Layout'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.create),
            tooltip: 'Search',
            onPressed: () {
              print('Pressed search');
            },
          ),
          const TopBarMenu(),
        ],
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              key: const Key('complex-scroll'), // this key is used by the driver test
              controller: ScrollController(),  // So that the scroll offset can be tracked
              itemBuilder: (BuildContext context, int index) {
                if (index.isEven)
                  return FancyImageItem(index, key: PageStorageKey<int>(index));
                else
                  return FancyGalleryItem(index, key: PageStorageKey<int>(index));
              },
            ),
          ),
          const BottomBar(),
        ],
      ),
      drawer: const GalleryDrawer(),
    );
  }
}

class TopBarMenu extends StatelessWidget {
  const TopBarMenu({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<String>(
      onSelected: (String value) { print('Selected: $value'); },
      itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
        const PopupMenuItem<String>(
          value: 'Friends',
          child: MenuItemWithIcon(Icons.people, 'Friends', '5 new'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.group, 'Groups', '14'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.image, 'Pictures', '12'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33'),
        ),
        const PopupMenuItem<String>(
          value: 'Friends',
          child: MenuItemWithIcon(Icons.people, 'Friends', '5'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.event, 'Events', '12'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.group, 'Groups', '14'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.image, 'Pictures', '12'),
        ),
        const PopupMenuItem<String>(
          value: 'Events',
          child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33'),
        ),
      ],
    );
  }
}

class MenuItemWithIcon extends StatelessWidget {
  const MenuItemWithIcon(this.icon, this.title, this.subtitle, {Key? key}) : super(key: key);

  final IconData icon;
  final String title;
  final String subtitle;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Icon(icon),
        Padding(
          padding: const EdgeInsets.only(left: 8.0, right: 8.0),
          child: Text(title),
        ),
        Text(subtitle, style: Theme.of(context).textTheme.caption),
      ],
    );
  }
}

class FancyImageItem extends StatelessWidget {
  const FancyImageItem(this.index, {Key? key}) : super(key: key);

  final int index;

  @override
  Widget build(BuildContext context) {
    return ListBody(
      children: <Widget>[
        UserHeader('Ali Connors $index'),
        const ItemDescription(),
        const ItemImageBox(),
        const InfoBar(),
        const Padding(
          padding: EdgeInsets.symmetric(horizontal: 8.0),
          child: Divider(),
        ),
        const IconBar(),
        const FatDivider(),
      ],
    );
  }
}

class FancyGalleryItem extends StatelessWidget {
  const FancyGalleryItem(this.index, {Key? key}) : super(key: key);

  final int index;
  @override
  Widget build(BuildContext context) {
    return ListBody(
      children: <Widget>[
        const UserHeader('Ali Connors'),
        ItemGalleryBox(index),
        const InfoBar(),
        const Padding(
          padding: EdgeInsets.symmetric(horizontal: 8.0),
          child: Divider(),
        ),
        const IconBar(),
        const FatDivider(),
      ],
    );
  }
}

class InfoBar extends StatelessWidget {
  const InfoBar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          const MiniIconWithText(Icons.thumb_up, '42'),
          Text('3 Comments', style: Theme.of(context).textTheme.caption),
        ],
      ),
    );
  }
}

class IconBar extends StatelessWidget {
  const IconBar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(left: 16.0, right: 16.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: const <Widget>[
          IconWithText(Icons.thumb_up, 'Like'),
          IconWithText(Icons.comment, 'Comment'),
          IconWithText(Icons.share, 'Share'),
        ],
      ),
    );
  }
}

class IconWithText extends StatelessWidget {
  const IconWithText(this.icon, this.title, {Key? key}) : super(key: key);

  final IconData icon;
  final String title;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        IconButton(
          icon: Icon(icon),
          onPressed: () { print('Pressed $title button'); },
        ),
        Text(title),
      ],
    );
  }
}

class MiniIconWithText extends StatelessWidget {
  const MiniIconWithText(this.icon, this.title, {Key? key}) : super(key: key);

  final IconData icon;
  final String title;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.only(right: 8.0),
          child: Container(
            width: 16.0,
            height: 16.0,
            decoration: BoxDecoration(
              color: Theme.of(context).primaryColor,
              shape: BoxShape.circle,
            ),
            child: Icon(icon, color: Colors.white, size: 12.0),
          ),
        ),
        Text(title, style: Theme.of(context).textTheme.caption),
      ],
    );
  }
}

class FatDivider extends StatelessWidget {
  const FatDivider({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 8.0,
      color: Theme.of(context).dividerColor,
    );
  }
}

class UserHeader extends StatelessWidget {
  const UserHeader(this.userName, {Key? key}) : super(key: key);

  final String userName;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          const Padding(
            padding: EdgeInsets.only(right: 8.0),
            child: Image(
              image: AssetImage('packages/flutter_gallery_assets/people/square/ali.png'),
              width: 32.0,
              height: 32.0,
            ),
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                RichText(text: TextSpan(
                  style: Theme.of(context).textTheme.bodyText2,
                  children: <TextSpan>[
                    TextSpan(text: userName, style: const TextStyle(fontWeight: FontWeight.bold)),
                    const TextSpan(text: ' shared a new '),
                    const TextSpan(text: 'photo', style: TextStyle(fontWeight: FontWeight.bold)),
                  ],
                )),
                Row(
                  children: <Widget>[
                    Text('Yesterday at 11:55 • ', style: Theme.of(context).textTheme.caption),
                    Icon(Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption!.color),
                  ],
                ),
              ],
            ),
          ),
          const TopBarMenu(),
        ],
      ),
    );
  }
}

class ItemDescription extends StatelessWidget {
  const ItemDescription({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Padding(
      padding: EdgeInsets.all(8.0),
      child: Text('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'),
    );
  }
}

class ItemImageBox extends StatelessWidget {
  const ItemImageBox({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Card(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Stack(
              children: <Widget>[
                const SizedBox(
                  height: 230.0,
                  child: Image(
                    image: AssetImage('packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png')
                  ),
                ),
                Theme(
                  data: ThemeData.dark(),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      IconButton(
                        icon: const Icon(Icons.edit),
                        onPressed: () { print('Pressed edit button'); },
                      ),
                      IconButton(
                        icon: const Icon(Icons.zoom_in),
                        onPressed: () { print('Pressed zoom button'); },
                      ),
                    ],
                  ),
                ),
                Positioned(
                  bottom: 4.0,
                  left: 4.0,
                  child: Container(
                    decoration: BoxDecoration(
                      color: Colors.black54,
                      borderRadius: BorderRadius.circular(2.0),
                    ),
                    padding: const EdgeInsets.all(4.0),
                    child: RichText(
                      text: const TextSpan(
                        style: TextStyle(color: Colors.white),
                        children: <TextSpan>[
                          TextSpan(
                            text: 'Photo by '
                          ),
                          TextSpan(
                            style: TextStyle(fontWeight: FontWeight.bold),
                            text: 'Chris Godley',
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            )
            ,
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Text('Artisans of Southern India', style: Theme.of(context).textTheme.bodyText1),
                  Text('Silk Spinners', style: Theme.of(context).textTheme.bodyText2),
                  Text('Sivaganga, Tamil Nadu', style: Theme.of(context).textTheme.caption),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class ItemGalleryBox extends StatelessWidget {
  const ItemGalleryBox(this.index, {Key? key}) : super(key: key);

  final int index;

  @override
  Widget build(BuildContext context) {
    final List<String> tabNames = <String>[
      'A', 'B', 'C', 'D',
    ];

    return SizedBox(
      height: 200.0,
      child: DefaultTabController(
        length: tabNames.length,
        child: Column(
          children: <Widget>[
            Expanded(
              child: TabBarView(
                children: tabNames.map<Widget>((String tabName) {
                  return Container(
                    key: PageStorageKey<String>(tabName),
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Card(
                        child: Column(
                          children: <Widget>[
                            Expanded(
                              child: Container(
                                color: Theme.of(context).primaryColor,
                                child: Center(
                                  child: Text(tabName, style: Theme.of(context).textTheme.headline5!.copyWith(color: Colors.white)),
                                ),
                              ),
                            ),
                            Row(
                              children: <Widget>[
                                IconButton(
                                  icon: const Icon(Icons.share),
                                  onPressed: () { print('Pressed share'); },
                                ),
                                IconButton(
                                  icon: const Icon(Icons.event),
                                  onPressed: () { print('Pressed event'); },
                                ),
                                Expanded(
                                  child: Padding(
                                    padding: const EdgeInsets.only(left: 8.0),
                                    child: Text('This is item $tabName'),
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  );
                }).toList(),
              ),
            ),
            const TabPageSelector(),
          ],
        ),
      ),
    );
  }
}

class BottomBar extends StatelessWidget {
  const BottomBar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(
            color: Theme.of(context).dividerColor,
          ),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: const <Widget>[
          BottomBarButton(Icons.new_releases, 'News'),
          BottomBarButton(Icons.people, 'Requests'),
          BottomBarButton(Icons.chat, 'Messenger'),
          BottomBarButton(Icons.bookmark, 'Bookmark'),
          BottomBarButton(Icons.alarm, 'Alarm'),
        ],
      ),
    );
  }
}

class BottomBarButton extends StatelessWidget {
  const BottomBarButton(this.icon, this.title, {Key? key}) : super(key: key);

  final IconData icon;
  final String title;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: <Widget>[
          IconButton(
            icon: Icon(icon),
            onPressed: () { print('Pressed: $title'); },
          ),
          Text(title, style: Theme.of(context).textTheme.caption),
        ],
      ),
    );
  }
}

class GalleryDrawer extends StatelessWidget {
  const GalleryDrawer({ Key? key }) : super(key: key);

  void _changeTheme(BuildContext context, bool value) {
    ComplexLayoutApp.of(context)?.lightTheme = value;
  }

  void _changeScrollMode(BuildContext context, ScrollMode mode) {
    ComplexLayoutApp.of(context)?.scrollMode = mode;
  }

  @override
  Widget build(BuildContext context) {
    final ScrollMode currentMode = ComplexLayoutApp.of(context)!.scrollMode;
    return Drawer(
      // Note: for real apps, see the Gallery material Drawer demo. More
      // typically, a drawer would have a fixed header with a scrolling body
      // below it.
      child: ListView(
        key: const PageStorageKey<String>('gallery-drawer'),
        padding: EdgeInsets.zero,
        children: <Widget>[
          const FancyDrawerHeader(),
          ListTile(
            key: const Key('scroll-switcher'),
            title: const Text('Scroll Mode'),
            onTap: () {
              _changeScrollMode(context, currentMode == ScrollMode.complex ? ScrollMode.tile : ScrollMode.complex);
             Navigator.pop(context);
            },
            trailing: Text(currentMode == ScrollMode.complex ? 'Tile' : 'Complex'),
          ),
          ListTile(
            leading: const Icon(Icons.brightness_5),
            title: const Text('Light'),
            onTap: () { _changeTheme(context, true); },
            selected: ComplexLayoutApp.of(context)!.lightTheme,
            trailing: Radio<bool>(
              value: true,
              groupValue: ComplexLayoutApp.of(context)!.lightTheme,
              onChanged: (bool? value) { _changeTheme(context, value!); },
            ),
          ),
          ListTile(
            leading: const Icon(Icons.brightness_7),
            title: const Text('Dark'),
            onTap: () { _changeTheme(context, false); },
            selected: !ComplexLayoutApp.of(context)!.lightTheme,
            trailing: Radio<bool>(
              value: false,
              groupValue: ComplexLayoutApp.of(context)!.lightTheme,
              onChanged: (bool? value) { _changeTheme(context, value!); },
            ),
          ),
          const Divider(),
          ListTile(
            leading: const Icon(Icons.hourglass_empty),
            title: const Text('Animate Slowly'),
            selected: timeDilation != 1.0,
            onTap: () { ComplexLayoutApp.of(context)!.toggleAnimationSpeed(); },
            trailing: Checkbox(
              value: timeDilation != 1.0,
              onChanged: (bool? value) { ComplexLayoutApp.of(context)!.toggleAnimationSpeed(); },
            ),
          ),
        ],
      ),
    );
  }
}

class FancyDrawerHeader extends StatelessWidget {
  const FancyDrawerHeader({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.purple,
      height: 200.0,
      child: const SafeArea(
        bottom: false,
        child: Placeholder(),
      ),
    );
  }
}
