import 'package:diameter/components/forms/boolean_form_field.dart';
import 'package:diameter/components/forms/number_form_field.dart';
import 'package:diameter/utils/dialog_utils.dart';
import 'package:diameter/components/forms/auto_complete_dropdown_button.dart';
import 'package:diameter/models/settings.dart';
import 'package:diameter/navigation.dart';
import 'package:diameter/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class SettingsScreen extends StatefulWidget {
  static const String routeName = '/settings';

  const SettingsScreen({Key? key}) : super(key: key);

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

class _SettingsScreenState extends State<SettingsScreen> {
  late Settings _settings;

  final ScrollController _scrollController = ScrollController();

  bool _measurementsIsExpanded = true;
  bool _promptsIsExpanded = true;
  bool _formatIsExpanded = true;

  final _nutritionMeasurementLabelController = TextEditingController(text: '');
  final _glucoseMeasurementLabelController = TextEditingController(text: '');
  final _dateFormatController = TextEditingController(text: '');
  final _longDateFormatController = TextEditingController(text: '');
  final _timeFormatController = TextEditingController(text: '');
  final _longTimeFormatController = TextEditingController(text: '');

  final _insulinIncrementsController = TextEditingController(text: '');
  final _nutritionIncrementsController = TextEditingController(text: '');
  final _mmolPerLIncrementsController = TextEditingController(text: '');
  final _targetGlucoseMgPerDlController = TextEditingController(text: '');
  final _targetGlucoseMmolPerLController = TextEditingController(text: '');

  late bool _onlyDisplayActiveGlucoseMeasurement;
  late bool _displayBothGlucoseMeasurementsInDetailView;
  late bool _displayBothGlucoseMeasurementsInListView;

  late bool _showConfirmationDialogOnCancel;
  late bool _showConfirmationDialogOnDelete;
  late bool _showConfirmationDialogOnStopEvent;

  @override
  void initState() {
    super.initState();
    _settings = Settings.get();
    _nutritionMeasurementLabelController.text =
        nutritionMeasurementLabels[_settings.nutritionMeasurementIndex];
    _glucoseMeasurementLabelController.text =
        glucoseMeasurementLabels[_settings.glucoseMeasurementIndex];
    _insulinIncrementsController.text = _settings.insulinIncrements.toString();
    _nutritionIncrementsController.text =
        _settings.nutritionIncrements.toString();
    _mmolPerLIncrementsController.text =
        _settings.mmolPerLIncrements.toString();
    _targetGlucoseMgPerDlController.text =
        _settings.targetGlucoseMgPerDl.toInt().toString();
    _targetGlucoseMmolPerLController.text =
        _settings.targetGlucoseMmolPerL.toString();
    _onlyDisplayActiveGlucoseMeasurement = _settings.glucoseDisplayModeIndex ==
        GlucoseDisplayMode.activeOnly.index;
    _displayBothGlucoseMeasurementsInDetailView =
        _settings.glucoseDisplayModeIndex == GlucoseDisplayMode.both.index ||
            _settings.glucoseDisplayModeIndex ==
                GlucoseDisplayMode.bothForDetail.index;
    _displayBothGlucoseMeasurementsInListView =
        _settings.glucoseDisplayModeIndex == GlucoseDisplayMode.both.index ||
            _settings.glucoseDisplayModeIndex ==
                GlucoseDisplayMode.bothForList.index;
    _dateFormatController.text = _settings.dateFormat;
    _longDateFormatController.text = _settings.longDateFormat ?? '';
    _timeFormatController.text = _settings.timeFormat;
    _longTimeFormatController.text = _settings.longTimeFormat ?? '';
    _showConfirmationDialogOnCancel = _settings.showConfirmationDialogOnCancel;
    _showConfirmationDialogOnDelete = _settings.showConfirmationDialogOnDelete;
    _showConfirmationDialogOnStopEvent =
        _settings.showConfirmationDialogOnStopEvent;
  }

  @override
  void dispose() {
    _scrollController.dispose();
    _nutritionMeasurementLabelController.dispose();
    _glucoseMeasurementLabelController.dispose();
    _dateFormatController.dispose();
    _longDateFormatController.dispose();
    _timeFormatController.dispose();
    _longTimeFormatController.dispose();
    _insulinIncrementsController.dispose();
    _nutritionIncrementsController.dispose();
    _mmolPerLIncrementsController.dispose();
    _targetGlucoseMgPerDlController.dispose();
    _targetGlucoseMmolPerLController.dispose();
    super.dispose();
  }

  void reload({String? message}) {
    setState(() {
      _settings = Settings.get();
    });

    setState(() {
      if (message != null) {
        var snackBar = SnackBar(
          content: Text(message),
          duration: const Duration(seconds: 2),
        );
        ScaffoldMessenger.of(context)
          ..removeCurrentSnackBar()
          ..showSnackBar(snackBar);
      }
    });
  }

  void saveSettings() {
    Settings.put(Settings(
      id: _settings.id,
      nutritionMeasurementIndex: nutritionMeasurementLabels
          .indexOf(_nutritionMeasurementLabelController.text),
      glucoseMeasurementIndex: glucoseMeasurementLabels
          .indexOf(_glucoseMeasurementLabelController.text),
      glucoseDisplayModeIndex: _onlyDisplayActiveGlucoseMeasurement
          ? GlucoseDisplayMode.activeOnly.index
          : _displayBothGlucoseMeasurementsInDetailView &&
                  _displayBothGlucoseMeasurementsInListView
              ? GlucoseDisplayMode.both.index
              : _displayBothGlucoseMeasurementsInDetailView
                  ? GlucoseDisplayMode.bothForDetail.index
                  : GlucoseDisplayMode.bothForList.index,
      targetGlucoseMgPerDl:
          int.tryParse(_targetGlucoseMgPerDlController.text) ?? _settings.targetGlucoseMgPerDl,
      targetGlucoseMmolPerL:
          double.tryParse(_targetGlucoseMmolPerLController.text) ?? _settings.targetGlucoseMmolPerL,
      insulinIncrements:
          double.tryParse(_insulinIncrementsController.text) ?? _settings.insulinIncrements,
      nutritionIncrements:
          double.tryParse(_nutritionIncrementsController.text) ?? _settings.nutritionIncrements,
      mmolPerLIncrements:
          double.tryParse(_mmolPerLIncrementsController.text) ?? _settings.mmolPerLIncrements,
      dateFormat: _dateFormatController.text,
      longDateFormat: _longDateFormatController.text,
      timeFormat: _timeFormatController.text,
      longTimeFormat: _longTimeFormatController.text,
      showConfirmationDialogOnCancel: _showConfirmationDialogOnCancel,
      showConfirmationDialogOnDelete: _showConfirmationDialogOnDelete,
      showConfirmationDialogOnStopEvent: _showConfirmationDialogOnStopEvent,
    ));
    reload(message: 'Settings updated');
  }

  void onReset() {
    Settings.reset();
    reload(message: 'Settings have been reset to default');
  }

  void handleResetAction() async {
    DialogUtils.showConfirmationDialog(
      context: context,
      onConfirm: onReset,
      message: 'Are you sure you want to reset all settings?',
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Application Settings'),
      ),
      drawer: const Navigation(currentLocation: SettingsScreen.routeName),
      body: SingleChildScrollView(
        controller: _scrollController,
        padding: const EdgeInsets.all(10.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 10.0),
              child: GestureDetector(
                onTap: () => setState(() {
                  _measurementsIsExpanded = !_measurementsIsExpanded;
                }),
                child: Row(
                  children: [
                    Expanded(
                      child: Text(
                        'MEASUREMENTS',
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                    ),
                    Icon(_measurementsIsExpanded
                        ? Icons.expand_less
                        : Icons.expand_more),
                  ],
                ),
              ),
            ),
            Column(
              children: _measurementsIsExpanded
                  ? [
                      AutoCompleteDropdownButton<String>(
                        controller: _nutritionMeasurementLabelController,
                        selectedItem: _nutritionMeasurementLabelController.text,
                        label: 'Preferred Nutrition Measurement',
                        items: nutritionMeasurementLabels,
                        onChanged: (value) {
                          _nutritionMeasurementLabelController.text =
                              value ?? '';
                          saveSettings();
                        },
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: AutoCompleteDropdownButton<String>(
                          controller: _glucoseMeasurementLabelController,
                          selectedItem: _glucoseMeasurementLabelController.text,
                          label: 'Preferred Glucose Measurement',
                          items: glucoseMeasurementLabels,
                          onChanged: (value) {
                            _glucoseMeasurementLabelController.text =
                                value ?? '';
                            saveSettings();
                          },
                        ),
                      ),
                      Settings.glucoseMeasurement == GlucoseMeasurement.mgPerDl
                          ? NumberFormField(
                              label: 'Target glucose',
                              suffix: 'mg/dl',
                              controller: _targetGlucoseMgPerDlController,
                              showSteppers: false,
                              onChanged: (_) async {
                                await Future.delayed(
                                    const Duration(seconds: 1));
                                if (Settings.glucoseMeasurement ==
                                        GlucoseMeasurement.mgPerDl) {
                                          final value = int.tryParse(
                                      _targetGlucoseMgPerDlController.text);
                                  _targetGlucoseMmolPerLController.text = Utils
                                      .toStringMatchingTemplateFractionPrecision(
                                          Utils.convertMgPerDlToMmolPerL(value ?? 0),
                                          Settings.mmolPerLSteps);
                                  await Future.delayed(
                                      const Duration(seconds: 1));
                                  saveSettings();
                                }
                              },
                            )
                          : NumberFormField(
                              label: 'Target glucose',
                              suffix: 'mmol/l',
                              controller: _targetGlucoseMmolPerLController,
                              showSteppers: false,
                              onChanged: (_) async {
                                await Future.delayed(
                                    const Duration(seconds: 1));
                                if (Settings.glucoseMeasurement ==
                                    GlucoseMeasurement.mmolPerL) {
                                  final value = double.tryParse(
                                      _targetGlucoseMmolPerLController.text);
                                  _targetGlucoseMgPerDlController.text =
                                      Utils.convertMmolPerLToMgPerDl(value ?? 0)
                                          .toString();
                                  saveSettings();
                                }
                              },
                            ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: NumberFormField(
                            controller: _insulinIncrementsController,
                            showSteppers: false,
                            label: 'Insulin increment',
                            onChanged: (value) {
                              _insulinIncrementsController.text =
                                  (value ?? 0).toString();
                              saveSettings();
                            }),
                      ),
                      NumberFormField(
                          controller: _nutritionIncrementsController,
                          showSteppers: false,
                          label: 'Nutrition increment',
                          onChanged: (value) {
                            _nutritionIncrementsController.text =
                                (value ?? 0).toString();
                            saveSettings();
                          }),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: NumberFormField(
                            controller: _mmolPerLIncrementsController,
                            showSteppers: false,
                            label: 'Mmol/L increment',
                            onChanged: (value) {
                              _mmolPerLIncrementsController.text =
                                  (value ?? 0).toString();
                              saveSettings();
                            }),
                      ),
                      BooleanFormField(
                        value: _onlyDisplayActiveGlucoseMeasurement,
                        label: 'only display active glucose measurement',
                        onChanged: (value) {
                          _onlyDisplayActiveGlucoseMeasurement = value;
                          saveSettings();
                        },
                      ),
                      BooleanFormField(
                        value: _displayBothGlucoseMeasurementsInDetailView,
                        enabled: !_onlyDisplayActiveGlucoseMeasurement,
                        label:
                            'display both glucose measurements in detail view',
                        onChanged: (value) {
                          _displayBothGlucoseMeasurementsInDetailView = value;
                          saveSettings();
                        },
                      ),
                      BooleanFormField(
                        value: _displayBothGlucoseMeasurementsInListView,
                        enabled: !_onlyDisplayActiveGlucoseMeasurement,
                        label: 'display both glucose measurements in list view',
                        onChanged: (value) {
                          _displayBothGlucoseMeasurementsInListView = value;
                          saveSettings();
                        },
                      ),
                    ]
                  : [],
            ),
            const Divider(),
            Padding(
              padding: const EdgeInsets.only(bottom: 10.0),
              child: GestureDetector(
                onTap: () => setState(() {
                  _promptsIsExpanded = !_promptsIsExpanded;
                }),
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Expanded(
                      child: Text(
                        'CONFIRMATION PROMPTS',
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                    ),
                    Icon(_promptsIsExpanded
                        ? Icons.expand_less
                        : Icons.expand_more),
                  ],
                ),
              ),
            ),
            Column(
              children: _promptsIsExpanded
                  ? [
                      BooleanFormField(
                        value: _showConfirmationDialogOnCancel,
                        label:
                            'on cancelling edit or creation of a record if changes have already been made',
                        onChanged: (value) {
                          _showConfirmationDialogOnCancel = value;
                          saveSettings();
                        },
                      ),
                      BooleanFormField(
                        value: _showConfirmationDialogOnDelete,
                        label: 'on deleting a record',
                        onChanged: (value) {
                          _showConfirmationDialogOnDelete = value;
                          saveSettings();
                        },
                      ),
                      BooleanFormField(
                        value: _showConfirmationDialogOnStopEvent,
                        label: 'on stopping (ending) an event',
                        onChanged: (value) {
                          _showConfirmationDialogOnStopEvent = value;
                          saveSettings();
                        },
                      ),
                    ]
                  : [],
            ),
            const Divider(),
            Padding(
              padding: const EdgeInsets.only(bottom: 10.0),
              child: GestureDetector(
                onTap: () => setState(() {
                  _formatIsExpanded = !_formatIsExpanded;
                }),
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Expanded(
                      child: Text(
                        'TIME & DATE FORMAT',
                        style: Theme.of(context).textTheme.subtitle2,
                      ),
                    ),
                    Icon(_formatIsExpanded
                        ? Icons.expand_less
                        : Icons.expand_more),
                  ],
                ),
              ),
            ),
            Column(
              children: _formatIsExpanded
                  ? [
                      Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Expanded(
                            child: TextFormField(
                              controller: _dateFormatController,
                              decoration: const InputDecoration(
                                labelText: 'Date Format',
                              ),
                              validator: (value) {
                                if (value!.trim().isEmpty) {
                                  return 'Empty title';
                                }
                                return null;
                              },
                            ),
                          ),
                          Expanded(
                            child: Padding(
                              padding: const EdgeInsets.only(
                                  left: 5.0, bottom: 10.0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  const Text('Example', textScaleFactor: 0.75),
                                  Text(
                                    DateFormat(_dateFormatController.text)
                                        .format(DateTime.now()),
                                    textScaleFactor: 1.25,
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: Row(
                          crossAxisAlignment: CrossAxisAlignment.end,
                          children: [
                            Expanded(
                              child: TextFormField(
                                controller: _longDateFormatController,
                                decoration: const InputDecoration(
                                  labelText: 'Long Date Format',
                                ),
                                validator: (value) {
                                  if (value!.trim().isEmpty) {
                                    return 'Empty title';
                                  }
                                  return null;
                                },
                              ),
                            ),
                            Expanded(
                              child: Padding(
                                padding: const EdgeInsets.only(
                                    left: 5.0, bottom: 10.0),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    const Text('Example',
                                        textScaleFactor: 0.75),
                                    Text(
                                      DateFormat(_longDateFormatController.text)
                                          .format(DateTime.now()),
                                      textScaleFactor: 1.25,
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                      Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Expanded(
                            child: TextFormField(
                              controller: _timeFormatController,
                              decoration: const InputDecoration(
                                labelText: 'Time Format',
                              ),
                              validator: (value) {
                                if (value!.trim().isEmpty) {
                                  return 'Empty title';
                                }
                                return null;
                              },
                            ),
                          ),
                          Expanded(
                            child: Padding(
                              padding: const EdgeInsets.only(
                                  left: 5.0, bottom: 10.0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  const Text('Example', textScaleFactor: 0.75),
                                  Text(
                                    DateFormat(_timeFormatController.text)
                                        .format(DateTime.now()),
                                    textScaleFactor: 1.25,
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: Row(
                          crossAxisAlignment: CrossAxisAlignment.end,
                          children: [
                            Expanded(
                              child: TextFormField(
                                controller: _longTimeFormatController,
                                decoration: const InputDecoration(
                                  labelText: 'Long Time Format',
                                ),
                                validator: (value) {
                                  if (value!.trim().isEmpty) {
                                    return 'Empty title';
                                  }
                                  return null;
                                },
                              ),
                            ),
                            Expanded(
                              child: Padding(
                                padding: const EdgeInsets.only(
                                    left: 5.0, bottom: 10.0),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    const Text('Example',
                                        textScaleFactor: 0.75),
                                    Text(
                                      DateFormat(_longTimeFormatController.text)
                                          .format(DateTime.now()),
                                      textScaleFactor: 1.25,
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ]
                  : [],
            ),
          ],
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        child: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Row(
            children: [
              ElevatedButton.icon(
                onPressed: handleResetAction,
                icon: const Icon(
                  Icons.settings_backup_restore,
                  size: 18.0,
                ),
                label: const Text('RESET ALL'),
              ),
              const Spacer(),
            ],
          ),
        ),
      ),
    );
  }
}
