import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/stub/stub_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/ui/stub/stub_presenter.dart';
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
import 'package:invoiceninja_flutter/ui/stub/stub_list_item.dart';
import 'package:invoiceninja_flutter/ui/stub/stub_list_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';

class StubList extends StatefulWidget {
  const StubList({
    Key key,
    @required this.viewModel,
  }) : super(key: key);

  final StubListVM viewModel;

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

class _StubListState extends State<StubList> {
  EntityDataTableSource dataTableSource;

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

    final viewModel = widget.viewModel;

    dataTableSource = EntityDataTableSource(
        context: context,
        entityType: EntityType.stub,
        editingId: viewModel.state.stubUIState.editing.id,
        tableColumns: viewModel.tableColumns,
        entityList: viewModel.stubList,
        entityMap: viewModel.stubMap,
        entityPresenter: StubPresenter(),
        onTap: (BaseEntity stub) => viewModel.onStubTap(context, stub));
  }

  @override
  void didUpdateWidget(StubList oldWidget) {
    super.didUpdateWidget(oldWidget);

    final viewModel = widget.viewModel;
    dataTableSource.editingId = viewModel.state.stubUIState.editing.id;
    dataTableSource.entityList = viewModel.stubList;
    dataTableSource.entityMap = viewModel.stubMap;

    // ignore: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member
    dataTableSource.notifyListeners();
  }

  @override
  Widget build(BuildContext context) {
    final store = StoreProvider.of<AppState>(context);
    final viewModel = widget.viewModel;
    final state = viewModel.state;
    final listUIState = state.uiState.stubUIState.listUIState;
    final isInMultiselect = listUIState.isInMultiselect();
    final isList = state.prefState.moduleLayout == ModuleLayout.list;
    final stubList = viewModel.stubList;

    if (!viewModel.isLoaded) {
      return viewModel.isLoading ? LoadingIndicator() : SizedBox();
    } else if (viewModel.stubMap.isEmpty) {
      return HelpText(AppLocalization.of(context).noRecordsFound);
    }

    if (state.shouldSelectEntity(
        entityType: EntityType.stub, hasRecords: stubList.isNotEmpty)) {
      viewEntityById(
        context: context,
        entityType: EntityType.stub,
        entityId: stubList.isEmpty ? null : stubList.first,
      );
    }

    final listOrTable = () {
      if (isList) {
        return ListView.separated(
            separatorBuilder: (context, index) => ListDivider(),
            itemCount: viewModel.stubList.length,
            itemBuilder: (BuildContext context, index) {
              final stubId = viewModel.stubList[index];
              final stub = viewModel.stubMap[stubId];

              return StubListItem(
                user: viewModel.state.user,
                filter: viewModel.filter,
                stub: stub,
                onEntityAction: (EntityAction action) {
                  if (action == EntityAction.more) {
                    showEntityActionsDialog(
                      entities: [stub],
                      context: context,
                    );
                  } else {
                    handleStubAction(context, [stub], action);
                  }
                },
                onTap: () => viewModel.onStubTap(context, stub),
                onLongPress: () async {
                  final longPressIsSelection =
                      state.prefState.longPressSelectionIsDefault ?? true;
                  if (longPressIsSelection && !isInMultiselect) {
                    handleStubAction(
                        context, [stub], EntityAction.toggleMultiselect);
                  } else {
                    showEntityActionsDialog(
                      entities: [stub],
                      context: context,
                    );
                  }
                },
                isChecked: isInMultiselect && listUIState.isSelected(stub.id),
              );
            });
      } else {
        return SingleChildScrollView(
            child: Padding(
          padding: const EdgeInsets.all(12),
          child: PaginatedDataTable(
            onSelectAll: (value) {
              final stubs = viewModel.stubList
                  .map<StubEntity>(
                      (stubId) => viewModel.stubMap[stubId])
                  .where((stub) => value != listUIState.isSelected(stub.id))
                  .toList();
              handleStubAction(
                  context, stubs, EntityAction.toggleMultiselect);
            },
            columns: [
              if (!listUIState.isInMultiselect()) DataColumn(label: SizedBox()),
              ...viewModel.tableColumns.map((field) => DataColumn(
                  label: Text(AppLocalization.of(context).lookup(field)),
                  numeric: EntityPresenter.isFieldNumeric(field),
                  onSort: (int columnIndex, bool ascending) =>
                      store.dispatch(SortStubs(field)))),
            ],
            source: dataTableSource,
            header: DatatableHeader(
              entityType: EntityType.stub,
              onClearPressed: viewModel.onClearEntityFilterPressed,
            ),
          ),
        ));
      }
    };

    return RefreshIndicator(
      onRefresh: () => viewModel.onRefreshed(context),
      child: listOrTable(),
    );
  }
}
