import 'dart:async';
import 'dart:io';

import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:feature_discovery/feature_discovery.dart';
import 'package:flutter/material.dart' hide NestedScrollView;
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';

import '../local_storage/key_value_storage.dart';
import '../local_storage/sqflite_localpodcast.dart';
import '../state/audio_state.dart';
import '../state/download_state.dart';
import '../state/podcast_group.dart';
import '../state/setting_state.dart';
import '../type/episodebrief.dart';
import '../type/playlist.dart';
import '../util/audiopanel.dart';
import '../util/custom_popupmenu.dart';
import '../util/custom_widget.dart';
import '../util/episodegrid.dart';
import '../util/extension_helper.dart';
import 'audioplayer.dart';
import 'download_list.dart';
import 'home_groups.dart';
import 'home_menu.dart';
import 'import_ompl.dart';
import 'playlist.dart';
import 'search_podcast.dart';

const String addFeature = 'addFeature';
const String menuFeature = 'menuFeature';
const String playlistFeature = 'playlistFeature';
const String longTapFeature = 'longTapFeature';
const String groupsFeature = 'groupsFeature';
const String podcastFeature = 'podcastFeature';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  final GlobalKey<AudioPanelState> _playerKey = GlobalKey<AudioPanelState>();
  TabController _controller;
  Decoration _getIndicator(BuildContext context) {
    return UnderlineTabIndicator(
        borderSide: BorderSide(color: Theme.of(context).accentColor, width: 3),
        insets: EdgeInsets.only(
          left: 10.0,
          right: 10.0,
          top: 10.0,
        ));
  }

  final _androidAppRetain = MethodChannel("android_app_retain");
  var feature1OverflowMode = OverflowMode.clipContent;
  var feature1EnablePulsingAnimation = false;

  @override
  void initState() {
    super.initState();
    _controller = TabController(length: 3, vsync: this);
    FeatureDiscovery.isDisplayed(context, addFeature).then((value) {
      if (!value) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          FeatureDiscovery.discoverFeatures(
            context,
            const <String>{
              addFeature,
              menuFeature,
              playlistFeature,
              groupsFeature,
              podcastFeature,
            },
          );
        });
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  double top = 0;
  @override
  Widget build(BuildContext context) {
    var width = MediaQuery.of(context).size.width;
    var height = (width - 20) / 3 + 140;
    var settings = Provider.of<SettingState>(context, listen: false);
    final s = context.s;
    return AnnotatedRegion<SystemUiOverlayStyle>(
        value: SystemUiOverlayStyle(
          systemNavigationBarIconBrightness:
              Theme.of(context).accentColorBrightness,
          statusBarIconBrightness: Theme.of(context).accentColorBrightness,
          systemNavigationBarColor: Theme.of(context).primaryColor,
        ),
        child: Scaffold(
          key: _scaffoldKey,
          body: WillPopScope(
            onWillPop: () async {
              if (_playerKey.currentState != null &&
                  _playerKey.currentState.initSize > 100) {
                _playerKey.currentState.backToMini();
                return false;
              } else if (Platform.isAndroid) {
                _androidAppRetain.invokeMethod('sendToBackground');
                return false;
              } else {
                return true;
              }
            },
            child: SafeArea(
              child: Stack(
                children: <Widget>[
                  Column(
                    children: <Widget>[
                      Expanded(
                        child: NestedScrollView(
                          innerScrollPositionKeyBuilder: () {
                            return Key('tab${_controller.index}');
                          },
                          pinnedHeaderSliverHeightBuilder: () => 50,
                          headerSliverBuilder: (context, innerBoxScrolled) {
                            return <Widget>[
                              SliverToBoxAdapter(
                                child: Column(
                                  children: <Widget>[
                                    SizedBox(
                                      height: 50.0,
                                      child: Row(
                                        mainAxisAlignment:
                                            MainAxisAlignment.spaceBetween,
                                        children: <Widget>[
                                          DescribedFeatureOverlay(
                                            featureId: addFeature,
                                            tapTarget:
                                                Icon(Icons.add_circle_outline),
                                            title:
                                                Text(s.featureDiscoverySearch),
                                            backgroundColor: Colors.cyan[600],
                                            overflowMode: feature1OverflowMode,
                                            onDismiss: () {
                                              return Future.value(true);
                                            },
                                            description: Column(
                                              crossAxisAlignment:
                                                  CrossAxisAlignment.start,
                                              children: <Widget>[
                                                Text(s
                                                    .featureDiscoverySearchDes),
                                                FlatButton(
                                                  color: Colors.cyan[500],
                                                  padding:
                                                      const EdgeInsets.all(0),
                                                  child: Text(s.understood,
                                                      style: Theme.of(context)
                                                          .textTheme
                                                          .button
                                                          .copyWith(
                                                              color: Colors
                                                                  .white)),
                                                  onPressed: () async =>
                                                      FeatureDiscovery
                                                          .completeCurrentStep(
                                                              context),
                                                ),
                                                FlatButton(
                                                  color: Colors.cyan[500],
                                                  padding:
                                                      const EdgeInsets.all(0),
                                                  child: Text(s.dismiss,
                                                      style: Theme.of(context)
                                                          .textTheme
                                                          .button
                                                          .copyWith(
                                                              color: Colors
                                                                  .white)),
                                                  onPressed: () =>
                                                      FeatureDiscovery
                                                          .dismissAll(context),
                                                ),
                                              ],
                                            ),
                                            child: IconButton(
                                              tooltip: s.add,
                                              icon: const Icon(
                                                  Icons.add_circle_outline),
                                              onPressed: () async {
                                                await showSearch<int>(
                                                  context: context,
                                                  delegate: MyHomePageDelegate(
                                                      searchFieldLabel:
                                                          s.searchPodcast),
                                                );
                                              },
                                            ),
                                          ),
                                          GestureDetector(
                                            onTap: () => {
                                              Theme.of(context).brightness ==
                                                      Brightness.light
                                                  ? settings.setTheme =
                                                      ThemeMode.dark
                                                  : settings.setTheme =
                                                      ThemeMode.light
                                            },
                                            child: Image(
                                              image: Theme.of(context)
                                                          .brightness ==
                                                      Brightness.light
                                                  ? AssetImage(
                                                      'assets/text.png')
                                                  : AssetImage(
                                                      'assets/text_light.png'),
                                              height: 30,
                                            ),
                                          ),
                                          DescribedFeatureOverlay(
                                              featureId: menuFeature,
                                              tapTarget: Icon(Icons.more_vert),
                                              backgroundColor: Colors.cyan[500],
                                              onDismiss: () =>
                                                  Future.value(true),
                                              title:
                                                  Text(s.featureDiscoveryOMPL),
                                              description: Column(
                                                crossAxisAlignment:
                                                    CrossAxisAlignment.end,
                                                children: <Widget>[
                                                  Text(s
                                                      .featureDiscoveryOMPLDes),
                                                  FlatButton(
                                                    color: Colors.cyan[600],
                                                    padding:
                                                        const EdgeInsets.all(0),
                                                    child: Text(s.understood,
                                                        style: Theme.of(context)
                                                            .textTheme
                                                            .button
                                                            .copyWith(
                                                                color: Colors
                                                                    .white)),
                                                    onPressed: () async =>
                                                        FeatureDiscovery
                                                            .completeCurrentStep(
                                                                context),
                                                  ),
                                                  FlatButton(
                                                    color: Colors.cyan[600],
                                                    padding:
                                                        const EdgeInsets.all(0),
                                                    child: Text(s.dismiss,
                                                        style: Theme.of(context)
                                                            .textTheme
                                                            .button
                                                            .copyWith(
                                                                color: Colors
                                                                    .white)),
                                                    onPressed: () =>
                                                        FeatureDiscovery
                                                            .dismissAll(
                                                                context),
                                                  ),
                                                ],
                                              ),
                                              child: PopupMenu()),
                                        ],
                                      ),
                                    ),
                                    Import(),
                                  ],
                                ),
                              ),
                              SliverList(
                                delegate: SliverChildBuilderDelegate(
                                  (context, index) {
                                    return DescribedFeatureOverlay(
                                      featureId: groupsFeature,
                                      tapTarget: Center(
                                          child: Text(
                                        s.featureDiscoveryPodcast,
                                        textAlign: TextAlign.center,
                                      )),
                                      backgroundColor: Colors.cyan[500],
                                      enablePulsingAnimation: false,
                                      onDismiss: () => Future.value(true),
                                      title:
                                          Text(s.featureDiscoveryPodcastTitle),
                                      description: Column(
                                        crossAxisAlignment:
                                            CrossAxisAlignment.start,
                                        children: <Widget>[
                                          Text(s.featureDiscoveryPodcastDes),
                                          Row(
                                            children: [
                                              FlatButton(
                                                color: Colors.cyan[600],
                                                padding:
                                                    const EdgeInsets.all(0),
                                                child: Text(s.understood,
                                                    style: Theme.of(context)
                                                        .textTheme
                                                        .button
                                                        .copyWith(
                                                            color:
                                                                Colors.white)),
                                                onPressed: () async =>
                                                    FeatureDiscovery
                                                        .completeCurrentStep(
                                                            context),
                                              ),
                                              Padding(
                                                  padding: EdgeInsets.symmetric(
                                                      horizontal: 5)),
                                              FlatButton(
                                                color: Colors.cyan[600],
                                                padding:
                                                    const EdgeInsets.all(0),
                                                child: Text(s.dismiss,
                                                    style: Theme.of(context)
                                                        .textTheme
                                                        .button
                                                        .copyWith(
                                                            color:
                                                                Colors.white)),
                                                onPressed: () =>
                                                    FeatureDiscovery.dismissAll(
                                                        context),
                                              ),
                                            ],
                                          ),
                                        ],
                                      ),
                                      child: SizedBox(
                                        height: height,
                                        width: width,
                                        child: ScrollPodcasts(),
                                      ),
                                    );
                                  },
                                  childCount: 1,
                                ),
                              ),
                              SliverPersistentHeader(
                                delegate: _SliverAppBarDelegate(
                                  TabBar(
                                    indicator: _getIndicator(context),
                                    isScrollable: true,
                                    indicatorSize: TabBarIndicatorSize.tab,
                                    controller: _controller,
                                    tabs: <Widget>[
                                      Tab(
                                        child: Text(s.homeTabMenuRecent),
                                      ),
                                      Tab(
                                        child: Text(s.homeTabMenuFavotite),
                                      ),
                                      Tab(
                                        child: Text(s.download),
                                      )
                                    ],
                                  ),
                                ),
                                pinned: true,
                              ),
                            ];
                          },
                          body: ScrollConfiguration(
                            behavior: NoGrowBehavior(),
                            child: TabBarView(
                              controller: _controller,
                              children: <Widget>[
                                NestedScrollViewInnerScrollPositionKeyWidget(
                                    Key('tab0'),
                                    DescribedFeatureOverlay(
                                        featureId: podcastFeature,
                                        tapTarget: Text(
                                            s.featureDiscoveryEpisode,
                                            textAlign: TextAlign.center),
                                        backgroundColor: Colors.cyan[500],
                                        enablePulsingAnimation: false,
                                        onDismiss: () => Future.value(true),
                                        title: Text(
                                            s.featureDiscoveryEpisodeTitle),
                                        description: Column(
                                          crossAxisAlignment:
                                              CrossAxisAlignment.start,
                                          children: <Widget>[
                                            Text(s.featureDiscoveryEpisodeDes),
                                            Row(
                                              children: [
                                                FlatButton(
                                                  color: Colors.cyan[600],
                                                  padding:
                                                      const EdgeInsets.all(0),
                                                  child: Text(s.understood,
                                                      style: Theme.of(context)
                                                          .textTheme
                                                          .button
                                                          .copyWith(
                                                              color: Colors
                                                                  .white)),
                                                  onPressed: () async =>
                                                      FeatureDiscovery
                                                          .completeCurrentStep(
                                                              context),
                                                ),
                                                Padding(
                                                    padding:
                                                        EdgeInsets.symmetric(
                                                            horizontal: 5)),
                                                FlatButton(
                                                  color: Colors.cyan[600],
                                                  padding:
                                                      const EdgeInsets.all(0),
                                                  child: Text(s.dismiss,
                                                      style: Theme.of(context)
                                                          .textTheme
                                                          .button
                                                          .copyWith(
                                                              color: Colors
                                                                  .white)),
                                                  onPressed: () =>
                                                      FeatureDiscovery
                                                          .dismissAll(context),
                                                ),
                                              ],
                                            ),
                                          ],
                                        ),
                                        child: _RecentUpdate())),
                                NestedScrollViewInnerScrollPositionKeyWidget(
                                    Key('tab1'), _MyFavorite()),
                                NestedScrollViewInnerScrollPositionKeyWidget(
                                    Key('tab2'), _MyDownload()),
                              ],
                            ),
                          ),
                        ),
                      ),
                      Selector<AudioPlayerNotifier, bool>(
                          selector: (_, audio) => audio.playerRunning,
                          builder: (_, data, __) {
                            return Padding(
                              padding: EdgeInsets.only(bottom: data ? 60.0 : 0),
                            );
                          }),
                    ],
                  ),
                  Container(child: PlayerWidget(playerKey: _playerKey)),
                ],
              ),
            ),
          ),
        ));
  }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate(this._tabBar);
  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height + 2;
  @override
  double get maxExtent => _tabBar.preferredSize.height + 2;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    final s = context.s;
    return Container(
      color: context.scaffoldBackgroundColor,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              _tabBar,
              Spacer(),
              DescribedFeatureOverlay(
                  featureId: playlistFeature,
                  tapTarget: Icon(Icons.playlist_play),
                  backgroundColor: Colors.cyan[500],
                  title: Text(s.featureDiscoveryPlaylist),
                  onDismiss: () => Future.value(true),
                  description: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(s.featureDiscoveryPlaylistDes),
                      FlatButton(
                        color: Colors.cyan[600],
                        padding: const EdgeInsets.all(0),
                        child: Text(s.understood,
                            style: Theme.of(context)
                                .textTheme
                                .button
                                .copyWith(color: Colors.white)),
                        onPressed: () async =>
                            FeatureDiscovery.completeCurrentStep(context),
                      ),
                      FlatButton(
                        color: Colors.cyan[600],
                        padding: const EdgeInsets.all(0),
                        child: Text(s.dismiss,
                            style: Theme.of(context)
                                .textTheme
                                .button
                                .copyWith(color: Colors.white)),
                        onPressed: () => FeatureDiscovery.dismissAll(context),
                      ),
                    ],
                  ),
                  child: _PlaylistButton()),
            ],
          ),
          Container(height: 2, color: context.primaryColor),
        ],
      ),
    );
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return true;
  }
}

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

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

class __PlaylistButtonState extends State<_PlaylistButton> {
  bool _loadPlay;

  _getPlaylist() async {
    await Provider.of<AudioPlayerNotifier>(context, listen: false)
        .loadPlaylist();
    setState(() {
      _loadPlay = true;
    });
  }

  @override
  void initState() {
    super.initState();
    _loadPlay = false;
    _getPlaylist();
  }

  @override
  Widget build(BuildContext context) {
    var audio = context.watch<AudioPlayerNotifier>();
    final s = context.s;
    return MyPopupMenuButton<int>(
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(10))),
      elevation: 1,
      icon: Icon(Icons.playlist_play),
      tooltip: s.menu,
      itemBuilder: (context) => [
        MyPopupMenuItem(
          height: 50,
          value: 1,
          child: Container(
            decoration: BoxDecoration(
              //  color: Theme.of(context).accentColor,
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(10.0),
                  topRight: Radius.circular(10.0)),
            ),
            child: Selector<AudioPlayerNotifier, Tuple3<bool, Playlist, int>>(
              selector: (_, audio) =>
                  Tuple3(audio.playerRunning, audio.queue, audio.lastPositin),
              builder: (_, data, __) => !_loadPlay
                  ? Container(
                      height: 8.0,
                    )
                  : data.item1 || data.item2.playlist.length == 0
                      ? Container(
                          height: 8.0,
                        )
                      : InkWell(
                          borderRadius: BorderRadius.only(
                              topLeft: Radius.circular(10.0),
                              topRight: Radius.circular(10.0)),
                          onTap: () {
                            audio.playlistLoad();
                            Navigator.pop<int>(context);
                          },
                          child: Column(
                            children: <Widget>[
                              Padding(
                                padding: EdgeInsets.symmetric(vertical: 5),
                              ),
                              Stack(
                                alignment: Alignment.center,
                                children: <Widget>[
                                  CircleAvatar(
                                      radius: 20,
                                      backgroundImage: data
                                          .item2.playlist.first.avatarImage),
                                  Container(
                                    height: 40.0,
                                    width: 40.0,
                                    decoration: BoxDecoration(
                                        shape: BoxShape.circle,
                                        color: Colors.black12),
                                    child: Icon(
                                      Icons.play_arrow,
                                      color: Colors.white,
                                    ),
                                  ),
                                ],
                              ),
                              Padding(
                                padding: EdgeInsets.symmetric(vertical: 2),
                              ),
                              Container(
                                height: 70,
                                width: 140,
                                child: Column(
                                  children: <Widget>[
                                    Text(
                                      (data.item3 ~/ 1000).toTime,
                                      // style:
                                      // TextStyle(color: Colors.white)
                                    ),
                                    Text(
                                      data.item2.playlist.first.title,
                                      maxLines: 2,
                                      textAlign: TextAlign.center,
                                      overflow: TextOverflow.fade,
                                      // style: TextStyle(color: Colors.white),
                                    ),
                                  ],
                                ),
                              ),
                              Divider(
                                height: 1,
                              ),
                            ],
                          ),
                        ),
            ),
          ),
        ),
        PopupMenuItem(
          value: 0,
          child: Container(
            padding: EdgeInsets.only(left: 10),
            child: Row(
              children: <Widget>[
                Icon(Icons.playlist_play),
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 5.0),
                ),
                Text(s.homeMenuPlaylist),
              ],
            ),
          ),
        ),
        PopupMenuDivider(
          height: 1,
        ),
        PopupMenuItem(
          value: 2,
          child: Container(
            padding: EdgeInsets.only(left: 10),
            child: Row(
              children: <Widget>[
                Icon(Icons.history),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 5.0),
                ),
                Text(s.settingsHistory),
              ],
            ),
          ),
        ),
        PopupMenuDivider(
          height: 1,
        ),
      ],
      onSelected: (value) {
        if (value == 0) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => PlaylistPage(
                initPage: InitPage.playlist,
              ),
            ),
          );
        } else if (value == 2) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => PlaylistPage(
                initPage: InitPage.history,
              ),
            ),
          );
        }
      },
    );
  }
}

class _RecentUpdate extends StatefulWidget {
  @override
  _RecentUpdateState createState() => _RecentUpdateState();
}

class _RecentUpdateState extends State<_RecentUpdate>
    with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin {
  Future<List<EpisodeBrief>> _getRssItem(int top, List<String> group) async {
    var storage = KeyValueStorage(recentLayoutKey);
    var index = await storage.getInt(defaultValue: 1);
    if (_layout == null) _layout = Layout.values[index];

    var dbHelper = DBHelper();
    List<EpisodeBrief> episodes;
    if (group.first == 'All') {
      episodes = await dbHelper.getRecentRssItem(top);
    } else {
      episodes = await dbHelper.getGroupRssItem(top, group);
    }
    return episodes;
  }

  Future<int> _getUpdateCounts(List<String> group) async {
    var dbHelper = DBHelper();
    var episodes = <EpisodeBrief>[];
    if (group.first == 'All') {
      episodes = await dbHelper.getRecentNewRssItem();
    } else {
      episodes = await dbHelper.getGroupNewRssItem(group);
    }
    return episodes.length;
  }

  /// Load more episodes.
  _loadMoreEpisode() async {
    if (mounted) setState(() => _loadMore = true);
    await Future.delayed(Duration(seconds: 3));
    if (mounted) {
      setState(() {
        _top = _top + 30;
        _loadMore = false;
      });
    }
  }

  /// Episodes loaded first time.
  int _top = 90;

  /// Load more episodes when scroll to bottom.
  bool _loadMore;

  /// For group fliter.
  String _groupName;
  List<String> _group;
  Layout _layout;
  bool _scroll;
  @override
  void initState() {
    super.initState();
    _loadMore = false;
    _groupName = 'All';
    _group = ['All'];
    _scroll = false;
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
    final s = context.s;
    return Selector<GroupList, bool>(
        selector: (_, worker) => worker.created,
        builder: (context, created, child) {
          return FutureBuilder<List<EpisodeBrief>>(
            future: _getRssItem(_top, _group),
            builder: (context, snapshot) {
              return (snapshot.hasData)
                  ? snapshot.data.length == 0
                      ? Padding(
                          padding: EdgeInsets.only(top: 150),
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: [
                              Icon(LineIcons.cloud_download_alt_solid,
                                  size: 80, color: Colors.grey[500]),
                              Padding(
                                  padding: EdgeInsets.symmetric(vertical: 10)),
                              Text(
                                s.noEpisodeRecent,
                                style: TextStyle(color: Colors.grey[500]),
                              )
                            ],
                          ),
                        )
                      : NotificationListener<ScrollNotification>(
                          onNotification: (scrollInfo) {
                            if (scrollInfo is ScrollStartNotification &&
                                mounted &&
                                !_scroll) {
                              setState(() => _scroll = true);
                            }
                            if (scrollInfo.metrics.pixels ==
                                    scrollInfo.metrics.maxScrollExtent &&
                                snapshot.data.length == _top) {
                              if (!_loadMore) {
                                _loadMoreEpisode();
                              }
                            }
                            return true;
                          },
                          child: CustomScrollView(
                              key: PageStorageKey<String>('update'),
                              physics: const AlwaysScrollableScrollPhysics(),
                              slivers: <Widget>[
                                SliverToBoxAdapter(
                                  child: Container(
                                      height: 40,
                                      color: context.primaryColor,
                                      child: Material(
                                        color: Colors.transparent,
                                        child: Row(
                                          children: <Widget>[
                                            Consumer<GroupList>(
                                              builder:
                                                  (context, groupList, child) =>
                                                      Material(
                                                color: Colors.transparent,
                                                child: PopupMenuButton<String>(
                                                  shape: RoundedRectangleBorder(
                                                      borderRadius:
                                                          BorderRadius.all(
                                                              Radius.circular(
                                                                  10))),
                                                  elevation: 1,
                                                  tooltip: s.groupFilter,
                                                  child: Container(
                                                      padding:
                                                          EdgeInsets.symmetric(
                                                              horizontal: 20),
                                                      height: 50,
                                                      child: Row(
                                                        mainAxisSize:
                                                            MainAxisSize.min,
                                                        children: <Widget>[
                                                          Text(_groupName ==
                                                                  'All'
                                                              ? s.all
                                                              : _groupName),
                                                          Padding(
                                                            padding: EdgeInsets
                                                                .symmetric(
                                                                    horizontal:
                                                                        5),
                                                          ),
                                                          Icon(
                                                            LineIcons
                                                                .filter_solid,
                                                            size: 18,
                                                          )
                                                        ],
                                                      )),
                                                  itemBuilder: (context) => [
                                                    PopupMenuItem(
                                                        child: Row(children: [
                                                          Text(s.all),
                                                          Spacer(),
                                                          if (_groupName ==
                                                              'All')
                                                            DotIndicator()
                                                        ]),
                                                        value: 'All')
                                                  ]..addAll(groupList.groups
                                                      .map<
                                                              PopupMenuEntry<
                                                                  String>>(
                                                          (e) => PopupMenuItem(
                                                              value: e.name,
                                                              child: Row(
                                                                children: [
                                                                  Text(e.name),
                                                                  Spacer(),
                                                                  if (e.name ==
                                                                      _groupName)
                                                                    DotIndicator()
                                                                ],
                                                              )))
                                                      .toList()),
                                                  onSelected: (value) {
                                                    if (value == 'All') {
                                                      setState(() {
                                                        _groupName = 'All';
                                                        _group = ['All'];
                                                      });
                                                    } else {
                                                      for (var group
                                                          in groupList.groups) {
                                                        if (group.name ==
                                                            value) {
                                                          setState(() {
                                                            _groupName = value;
                                                            _group = group
                                                                .podcastList;
                                                          });
                                                        }
                                                      }
                                                    }
                                                  },
                                                ),
                                              ),
                                            ),
                                            Spacer(),
                                            FutureBuilder<int>(
                                                future:
                                                    _getUpdateCounts(_group),
                                                initialData: 0,
                                                builder: (context, snapshot) {
                                                  return snapshot.data != 0
                                                      ? Material(
                                                          color: Colors
                                                              .transparent,
                                                          child: IconButton(
                                                              tooltip: s
                                                                  .addNewEpisodeTooltip,
                                                              icon: SizedBox(
                                                                  height: 16,
                                                                  width: 21,
                                                                  child: CustomPaint(
                                                                      painter: AddToPlaylistPainter(
                                                                          context
                                                                              .textTheme
                                                                              .bodyText1
                                                                              .color,
                                                                          Colors
                                                                              .red))),
                                                              onPressed:
                                                                  () async {
                                                                await audio
                                                                    .addNewEpisode(
                                                                        _group);
                                                                if (mounted) {
                                                                  setState(
                                                                      () {});
                                                                }
                                                                Fluttertoast
                                                                    .showToast(
                                                                  msg: _groupName ==
                                                                          'All'
                                                                      ? s.addNewEpisodeAll(
                                                                          snapshot
                                                                              .data)
                                                                      : s.addEpisodeGroup(
                                                                          _groupName,
                                                                          snapshot
                                                                              .data),
                                                                  gravity:
                                                                      ToastGravity
                                                                          .BOTTOM,
                                                                );
                                                              }),
                                                        )
                                                      : Material(
                                                          color: Colors
                                                              .transparent,
                                                          child: IconButton(
                                                              tooltip: s
                                                                  .addNewEpisodeTooltip,
                                                              icon: SizedBox(
                                                                  height: 16,
                                                                  width: 21,
                                                                  child:
                                                                      CustomPaint(
                                                                          painter:
                                                                              AddToPlaylistPainter(
                                                                    context
                                                                        .textColor,
                                                                    context
                                                                        .textColor,
                                                                  ))),
                                                              onPressed: () {}),
                                                        );
                                                }),
                                            Material(
                                              color: Colors.transparent,
                                              child: LayoutButton(
                                                layout: _layout,
                                                onPressed: (layout) =>
                                                    setState(() {
                                                  _layout = layout;
                                                }),
                                              ),
                                            ),
                                          ],
                                        ),
                                      )),
                                ),
                                EpisodeGrid(
                                  episodes: snapshot.data,
                                  layout: _layout,
                                  initNum: _scroll ? 0 : 12,
                                ),
                                SliverList(
                                  delegate: SliverChildBuilderDelegate(
                                    (context, index) {
                                      return _loadMore
                                          ? Container(
                                              height: 2,
                                              child: LinearProgressIndicator())
                                          : Center();
                                    },
                                    childCount: 1,
                                  ),
                                ),
                              ]))
                  : Center();
            },
          );
        });
  }

  @override
  bool get wantKeepAlive => true;
}

class _MyFavorite extends StatefulWidget {
  @override
  _MyFavoriteState createState() => _MyFavoriteState();
}

class _MyFavoriteState extends State<_MyFavorite>
    with AutomaticKeepAliveClientMixin {
  Future<List<EpisodeBrief>> _getLikedRssItem(int top, int sortBy) async {
    var storage = KeyValueStorage(favLayoutKey);
    var index = await storage.getInt(defaultValue: 1);
    if (_layout == null) _layout = Layout.values[index];
    var dbHelper = DBHelper();
    var episodes = await dbHelper.getLikedRssItem(top, sortBy);
    return episodes;
  }

  _loadMoreEpisode() async {
    if (mounted) setState(() => _loadMore = true);
    await Future.delayed(Duration(seconds: 3));
    if (mounted) {
      setState(() {
        _top = _top + 30;
        _loadMore = false;
      });
    }
  }

  int _top = 90;
  bool _loadMore;
  Layout _layout;
  int _sortBy;
  @override
  void initState() {
    super.initState();
    _loadMore = false;
    _sortBy = 0;
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    final s = context.s;
    return Selector<AudioPlayerNotifier, bool>(
        selector: (_, audio) => audio.episodeState,
        builder: (context, episodeState, child) {
          return FutureBuilder<List<EpisodeBrief>>(
            future: _getLikedRssItem(_top, _sortBy),
            builder: (context, snapshot) {
              return (snapshot.hasData)
                  ? snapshot.data.length == 0
                      ? Padding(
                          padding: EdgeInsets.only(top: 150),
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: [
                              Icon(LineIcons.heartbeat_solid,
                                  size: 80, color: Colors.grey[500]),
                              Padding(
                                  padding: EdgeInsets.symmetric(vertical: 10)),
                              Text(
                                s.noEpisodeFavorite,
                                style: TextStyle(color: Colors.grey[500]),
                              )
                            ],
                          ),
                        )
                      : NotificationListener<ScrollNotification>(
                          onNotification: (scrollInfo) {
                            if (scrollInfo.metrics.pixels ==
                                    scrollInfo.metrics.maxScrollExtent &&
                                snapshot.data.length == _top) {
                              if (!_loadMore) {
                                _loadMoreEpisode();
                              }
                            }
                            return true;
                          },
                          child: CustomScrollView(
                            key: PageStorageKey<String>('favorite'),
                            slivers: <Widget>[
                              SliverToBoxAdapter(
                                child: Container(
                                    height: 40,
                                    color: context.primaryColor,
                                    child: Row(
                                      children: <Widget>[
                                        Material(
                                          color: Colors.transparent,
                                          child: PopupMenuButton<int>(
                                            shape: RoundedRectangleBorder(
                                                borderRadius: BorderRadius.all(
                                                    Radius.circular(10))),
                                            elevation: 1,
                                            tooltip: s.homeSubMenuSortBy,
                                            child: Container(
                                                height: 50,
                                                padding: EdgeInsets.symmetric(
                                                    horizontal: 20),
                                                child: Row(
                                                  mainAxisSize:
                                                      MainAxisSize.min,
                                                  children: <Widget>[
                                                    Text(s.homeSubMenuSortBy),
                                                    Padding(
                                                      padding:
                                                          EdgeInsets.symmetric(
                                                              horizontal: 5),
                                                    ),
                                                    Icon(
                                                      LineIcons
                                                          .hourglass_start_solid,
                                                      size: 18,
                                                    )
                                                  ],
                                                )),
                                            itemBuilder: (context) => [
                                              PopupMenuItem(
                                                value: 0,
                                                child: Row(
                                                  children: [
                                                    Text(s.updateDate),
                                                    Spacer(),
                                                    if (_sortBy == 0)
                                                      DotIndicator()
                                                  ],
                                                ),
                                              ),
                                              PopupMenuItem(
                                                value: 1,
                                                child: Row(
                                                  children: [
                                                    Text(s.likeDate),
                                                    Spacer(),
                                                    if (_sortBy == 1)
                                                      DotIndicator()
                                                  ],
                                                ),
                                              )
                                            ],
                                            onSelected: (value) {
                                              if (value == 0) {
                                                setState(() => _sortBy = 0);
                                              } else if (value == 1) {
                                                setState(() => _sortBy = 1);
                                              }
                                            },
                                          ),
                                        ),
                                        Spacer(),
                                        Material(
                                          color: Colors.transparent,
                                          child: LayoutButton(
                                            layout: _layout,
                                            onPressed: (layout) => setState(() {
                                              _layout = layout;
                                            }),
                                          ),
                                        ),
                                      ],
                                    )),
                              ),
                              EpisodeGrid(
                                episodes: snapshot.data,
                                layout: _layout,
                                initNum: 0,
                              ),
                              SliverList(
                                delegate: SliverChildBuilderDelegate(
                                  (context, index) {
                                    return _loadMore
                                        ? Container(
                                            height: 2,
                                            child: LinearProgressIndicator())
                                        : Center();
                                  },
                                  childCount: 1,
                                ),
                              ),
                            ],
                          ),
                        )
                  : Center();
            },
          );
        });
  }

  @override
  bool get wantKeepAlive => true;
}

class _MyDownload extends StatefulWidget {
  @override
  _MyDownloadState createState() => _MyDownloadState();
}

class _MyDownloadState extends State<_MyDownload>
    with AutomaticKeepAliveClientMixin {
  Layout _layout;
  _getLayout() async {
    var keyValueStorage = KeyValueStorage(downloadLayoutKey);
    var layout = await keyValueStorage.getInt(defaultValue: 1);
    if (_layout == null) {
      setState(() {
        _layout = Layout.values[layout];
      });
    }
  }

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

  @override
  Widget build(BuildContext context) {
    super.build(context);
    final s = context.s;
    return CustomScrollView(
      key: PageStorageKey<String>('download_list'),
      slivers: <Widget>[
        DownloadList(),
        SliverToBoxAdapter(
          child: _layout == null
              ? Center()
              : Container(
                  height: 40,
                  color: context.primaryColor,
                  child: Row(
                    children: <Widget>[
                      Container(
                          padding: EdgeInsets.symmetric(horizontal: 20),
                          child: Text(s.downloaded)),
                      Spacer(),
                      Material(
                        color: Colors.transparent,
                        child: LayoutButton(
                          layout: _layout,
                          onPressed: (layout) => setState(() {
                            _layout = layout;
                          }),
                        ),
                      ),
                    ],
                  )),
        ),
        Consumer<DownloadState>(
          builder: (_, downloader, __) {
            var episodes = downloader.episodeTasks
                .where((task) => task.status.value == 3)
                .toList()
                .map((e) => e.episode)
                .toList()
                .reversed
                .toList();
            return episodes.length == 0
                ? SliverToBoxAdapter(
                    child: Padding(
                      padding: EdgeInsets.only(top: 110),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          Icon(LineIcons.download_solid,
                              size: 80, color: Colors.grey[500]),
                          Padding(padding: EdgeInsets.symmetric(vertical: 10)),
                          Text(
                            s.noEpisodeDownload,
                            style: TextStyle(color: Colors.grey[500]),
                          )
                        ],
                      ),
                    ),
                  )
                : EpisodeGrid(
                    episodes: episodes,
                    layout: _layout,
                    initNum: 0,
                  );
          },
        ),
      ],
    );
  }

  @override
  bool get wantKeepAlive => true;
}
