// Copyright 2015 The Chromium 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(
    new ComplexLayoutApp()
  );
}

enum ScrollMode { complex, tile }

class ComplexLayoutApp extends StatefulWidget {
  @override
  ComplexLayoutAppState createState() => new ComplexLayoutAppState();

  static ComplexLayoutAppState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutAppState>());
}

class ComplexLayoutAppState extends State<ComplexLayoutApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: lightTheme ? new ThemeData.light() : new 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 new Scaffold(
      appBar: new AppBar(title: const Text('Tile Scrolling Layout')),
      body: new ListView.builder(
        key: const Key('tiles-scroll'),
        itemCount: 200,
        itemBuilder: (BuildContext context, int index) {
          return new Padding(
            padding: const EdgeInsets.all(5.0),
            child: new Material(
              elevation: (index % 5 + 1).toDouble(),
              color: Colors.white,
              child: new IconBar(),
            ),
          );
        }
      ),
      drawer: const GalleryDrawer(),
    );
  }
}

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

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

  static ComplexLayoutState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<ComplexLayoutState>());
}

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

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

class MenuItemWithIcon extends StatelessWidget {
  const MenuItemWithIcon(this.icon, this.title, this.subtitle);

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

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new Icon(icon),
        new Padding(
          padding: const EdgeInsets.only(left: 8.0, right: 8.0),
          child: new Text(title)
        ),
        new 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 new ListBody(
      children: <Widget>[
        new UserHeader('Ali Connors $index'),
        new ItemDescription(),
        new ItemImageBox(),
        new InfoBar(),
        const Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8.0),
          child: const Divider()
        ),
        new IconBar(),
        new FatDivider()
      ]
    );
  }
}

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

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

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

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

class IconWithText extends StatelessWidget {
  const IconWithText(this.icon, this.title);

  final IconData icon;
  final String title;

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

class MiniIconWithText extends StatelessWidget {
  const MiniIconWithText(this.icon, this.title);

  final IconData icon;
  final String title;

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

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

class UserHeader extends StatelessWidget {
  const UserHeader(this.userName);

  final String userName;

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

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

class ItemImageBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: const EdgeInsets.all(8.0),
      child: new Card(
        child: new Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            new Stack(
              children: <Widget>[
                const SizedBox(
                  height: 230.0,
                  child: const Image(
                    image: const AssetImage('packages/flutter_gallery_assets/top_10_australian_beaches.png')
                  )
                ),
                new Theme(
                  data: new ThemeData.dark(),
                  child: new Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      new IconButton(
                        icon: const Icon(Icons.edit),
                        onPressed: () { print('Pressed edit button'); }
                      ),
                      new IconButton(
                        icon: const Icon(Icons.zoom_in),
                        onPressed: () { print('Pressed zoom button'); }
                      ),
                    ]
                  )
                ),
                new Positioned(
                  bottom: 4.0,
                  left: 4.0,
                  child: new Container(
                    decoration: new BoxDecoration(
                      color: Colors.black54,
                      borderRadius: new BorderRadius.circular(2.0)
                    ),
                    padding: const EdgeInsets.all(4.0),
                    child: const RichText(
                      text: const TextSpan(
                        style: const TextStyle(color: Colors.white),
                        children: const <TextSpan>[
                          const TextSpan(
                            text: 'Photo by '
                          ),
                          const TextSpan(
                            style: const TextStyle(fontWeight: FontWeight.bold),
                            text: 'Magic Mike'
                          )
                        ]
                      )
                    )
                  )
                )
              ]
            )
            ,
            new Padding(
              padding: const EdgeInsets.all(8.0),
              child: new Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  new Text('Where can you find that amazing sunset?', style: Theme.of(context).textTheme.body2),
                  new Text('The sun sets over stinson beach', style: Theme.of(context).textTheme.body1),
                  new Text('flutter.io/amazingsunsets', style: Theme.of(context).textTheme.caption)
                ]
              )
            )
          ]
        )
      )
    );
  }
}

class ItemGalleryBox extends StatelessWidget {
  const ItemGalleryBox(this.index);

  final int index;

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

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

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

class BottomBarButton extends StatelessWidget {
  const BottomBarButton(this.icon, this.title);

  final IconData icon;
  final String title;

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: const EdgeInsets.all(8.0),
      child: new Column(
        children: <Widget>[
          new IconButton(
            icon: new Icon(icon),
            onPressed: () { print('Pressed: $title'); }
          ),
          new 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 new 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: new ListView(
        key: const PageStorageKey<String>('gallery-drawer'),
        padding: EdgeInsets.zero,
        children: <Widget>[
          new FancyDrawerHeader(),
          new ListTile(
            key: const Key('scroll-switcher'),
            onTap: () { _changeScrollMode(context, currentMode == ScrollMode.complex ? ScrollMode.tile : ScrollMode.complex); },
            trailing: new Text(currentMode == ScrollMode.complex ? 'Tile' : 'Complex')
          ),
          new ListTile(
            leading: const Icon(Icons.brightness_5),
            title: const Text('Light'),
            onTap: () { _changeTheme(context, true); },
            selected: ComplexLayoutApp.of(context).lightTheme,
            trailing: new Radio<bool>(
              value: true,
              groupValue: ComplexLayoutApp.of(context).lightTheme,
              onChanged: (bool value) { _changeTheme(context, value); }
            ),
          ),
          new ListTile(
            leading: const Icon(Icons.brightness_7),
            title: const Text('Dark'),
            onTap: () { _changeTheme(context, false); },
            selected: !ComplexLayoutApp.of(context).lightTheme,
            trailing: new Radio<bool>(
              value: false,
              groupValue: ComplexLayoutApp.of(context).lightTheme,
              onChanged: (bool value) { _changeTheme(context, value); },
            ),
          ),
          const Divider(),
          new ListTile(
            leading: const Icon(Icons.hourglass_empty),
            title: const Text('Animate Slowly'),
            selected: timeDilation != 1.0,
            onTap: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); },
            trailing: new Checkbox(
              value: timeDilation != 1.0,
              onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }
            ),
          ),
        ],
      ),
    );
  }
}

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