import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/scaffolds/tab.dart';
import 'package:git_touch/scaffolds/utils.dart';

class TabStatefulScaffold<T> extends StatefulWidget {
  final Widget title;
  final Widget Function(T payload, int activeTab) bodyBuilder;
  final Future<T> Function(int activeTab) fetchData;
  final List<String> tabs;
  final Widget Function(T payload, void Function() refresh) actionBuilder;

  TabStatefulScaffold({
    @required this.title,
    @required this.bodyBuilder,
    @required this.fetchData,
    @required this.tabs,
    this.actionBuilder,
  });

  @override
  _TabStatefulScaffoldState<T> createState() => _TabStatefulScaffoldState();
}

class _TabStatefulScaffoldState<T> extends State<TabStatefulScaffold<T>> {
  bool _loading;
  T _payload0;
  T _payload1;
  T _payload2;
  String _error = '';
  int _activeTab = 0;

  T _getPayload(int selected) {
    switch (selected) {
      case 0:
        return _payload0;
      case 1:
        return _payload1;
      case 2:
        return _payload2;
      default:
        throw '';
    }
  }

  T get _payload => _getPayload(_activeTab);

  set _payload(T v) {
    switch (_activeTab) {
      case 0:
        _payload0 = v;
        break;
      case 1:
        _payload1 = v;
        break;
      case 2:
        _payload2 = v;
        break;
    }
  }

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

  Future<void> _refresh() async {
    try {
      setState(() {
        _error = '';
        _loading = true;
      });
      _payload = await widget.fetchData(_activeTab);
    } catch (err) {
      _error = err.toString();
      throw err;
    } finally {
      if (mounted) {
        setState(() {
          _loading = false;
        });
      }
    }
  }

  Future<void> _switch(int selected) async {
    if (_loading) return;

    setState(() {
      _activeTab = selected;
    });
    if (_getPayload(selected) == null) {
      await _refresh();
    }
  }

  @override
  Widget build(BuildContext context) {
    return TabScaffold(
      title: widget.title,
      action: widget.actionBuilder == null
          ? null
          : widget.actionBuilder(_payload, _refresh),
      tabs: widget.tabs,
      activeTab: _activeTab,
      onTabSwitch: _switch,
      onRefresh: _refresh,
      body: ErrorLoadingWrapper(
        bodyBuilder: () => widget.bodyBuilder(_payload, _activeTab),
        error: _error,
        loading: _payload == null,
        reload: _refresh,
      ),
    );
  }
}
