
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'package:provider/provider.dart';

import '../../../api/marianumcloud/webdav/queries/listFiles/cacheableFile.dart';
import '../../../api/marianumcloud/webdav/queries/listFiles/listFilesCache.dart';
import '../../../api/marianumcloud/webdav/queries/listFiles/listFilesResponse.dart';
import '../../../api/marianumcloud/webdav/webdavApi.dart';
import '../../../model/files/filesProps.dart';
import '../../../storage/base/settingsProvider.dart';
import '../../../widget/loadingSpinner.dart';
import '../../../widget/placeholderView.dart';
import '../../../widget/filePick.dart';
import 'fileUploadDialog.dart';
import 'fileElement.dart';

class Files extends StatefulWidget {
  final List<String> path;
  const Files(this.path, {Key? key}) : super(key: key);

  @override
  State<Files> createState() => _FilesState();
}

class BetterSortOption {
  String displayName;
  int Function(CacheableFile, CacheableFile) compare;
  IconData icon;

  BetterSortOption({required this.displayName, required this.icon, required this.compare});
}

enum SortOption {
  name,
  date,
  size
}

class SortOptions {
  static Map<SortOption, BetterSortOption> options = {
    SortOption.name: BetterSortOption(
      displayName: "Name",
      icon: Icons.sort_by_alpha_outlined,
      compare: (CacheableFile a, CacheableFile b) => a.name.compareTo(b.name)
    ),
    SortOption.date: BetterSortOption(
      displayName: "Datum",
      icon: Icons.history_outlined,
      compare: (CacheableFile a, CacheableFile b) => a.modifiedAt!.compareTo(b.modifiedAt!)
    ),
    SortOption.size: BetterSortOption(
      displayName: "Größe",
      icon: Icons.sd_card_outlined,
      compare: (CacheableFile a, CacheableFile b) {
        if(a.isDirectory || b.isDirectory) return a.isDirectory ? 1 : 0;
        if(a.size == null) return 0;
        if(b.size == null) return 1;
        return a.size!.compareTo(b.size!);
      }
    )
  };

  static BetterSortOption getOption(SortOption option) {
    return options[option]!;
  }
}

class _FilesState extends State<Files> {
  FilesProps props = FilesProps();
  ListFilesResponse? data;

  late SettingsProvider settings = Provider.of<SettingsProvider>(context, listen: false);

  SortOption currentSort = SortOption.name;
  bool currentSortDirection = true;

  @override
  void initState() {
    super.initState();
    currentSort = settings.val().fileSettings.sortBy;
    currentSortDirection = settings.val().fileSettings.ascending;
    _query();
  }

  void _query() {
    ListFilesCache(
        path: widget.path.isEmpty ? "/" : widget.path.join("/"),
        onUpdate: (ListFilesResponse d) {
          if(!context.mounted) return; // prevent setState when widget is possibly already disposed
          setState(() {
            data = d;
          });
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    List<CacheableFile> files = data?.sortBy(
      sortOption: currentSort,
      foldersToTop: Provider.of<SettingsProvider>(context).val().fileSettings.sortFoldersToTop,
      reversed: currentSortDirection
    ) ?? List<CacheableFile>.empty();

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.path.isNotEmpty ? widget.path.last : "Dateien"),
        actions: [
          // IconButton(
          //   icon: const Icon(Icons.search),
          //   onPressed: () => {
          //     // TODO implement search
          //   },
          // ),
          PopupMenuButton<bool>(
            icon: Icon(currentSortDirection ? Icons.text_rotate_up : Icons.text_rotation_down),
            itemBuilder: (context) {
              return [true, false].map((e) => PopupMenuItem<bool>(
                  value: e,
                  enabled: e != currentSortDirection,
                  child: Row(
                    children: [
                      Icon(e ? Icons.text_rotate_up : Icons.text_rotation_down, color: Theme.of(context).colorScheme.onSurface),
                      const SizedBox(width: 15),
                      Text(e ? "Aufsteigend" : "Absteigend")
                    ],
                  )
              )).toList();
            },
            onSelected: (e) {
              setState(() {
                currentSortDirection = e;
                settings.val(write: true).fileSettings.ascending = e;
              });
            },
          ),
          PopupMenuButton<SortOption>(
            icon: const Icon(Icons.sort),
            itemBuilder: (context) {
              return SortOptions.options.keys.map((key) => PopupMenuItem<SortOption>(
                  value: key,
                  enabled: key != currentSort,
                  child: Row(
                    children: [
                      Icon(SortOptions.getOption(key).icon, color: Theme.of(context).colorScheme.onSurface),
                      const SizedBox(width: 15),
                      Text(SortOptions.getOption(key).displayName)
                    ],
                  )
              )).toList();
            },
            onSelected: (e) {
              setState(() {
                currentSort = e;
                settings.val(write: true).fileSettings.sortBy = e;
              });
            },
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        heroTag: "uploadFile",
        backgroundColor: Theme.of(context).primaryColor,
        onPressed: () {
          showDialog(context: context, builder: (context) {
            return SimpleDialog(
              children: [
                ListTile(
                  leading: const Icon(Icons.create_new_folder_outlined),
                  title: const Text("Ordner erstellen"),
                  onTap: () {
                    Navigator.of(context).pop();
                    showDialog(context: context, builder: (context) {
                      var inputController = TextEditingController();
                      return AlertDialog(
                        title: const Text("Neuer Ordner"),
                        content: TextField(
                          controller: inputController,
                          decoration: const InputDecoration(
                            labelText: "Name",
                          ),
                        ),
                        actions: [
                          TextButton(onPressed: () {
                            Navigator.of(context).pop();
                          }, child: const Text("Abbrechen")),
                          TextButton(onPressed: () {
                            WebdavApi.webdav.then((webdav) {
                              webdav.mkcol("${widget.path.join("/")}/${inputController.text}").then((value) => _query());
                            });
                            Navigator.of(context).pop();
                          }, child: const Text("Ordner erstellen")),
                        ],
                      );
                    });
                  },
                ),
                ListTile(
                  leading: const Icon(Icons.upload_file),
                  title: const Text("Aus Dateien hochladen"),
                  onTap: () {
                    context.loaderOverlay.show();
                    FilePick.documentPick().then((value) {
                      mediaUpload(value);
                    });
                    Navigator.of(context).pop();
                  },
                ),
                Visibility(
                  visible: !Platform.isIOS,
                  child: ListTile(
                    leading: const Icon(Icons.add_a_photo_outlined),
                    title: const Text("Aus Gallerie hochladen"),
                    onTap: () {
                      context.loaderOverlay.show();
                      FilePick.galleryPick().then((value) {
                        mediaUpload(value?.path);
                      });
                      Navigator.of(context).pop();
                    },
                  ),
                ),
              ],
            );
          });
        },
        child: const Icon(Icons.add),
      ),
      body: data == null ? const LoadingSpinner() : data!.files.isEmpty ? const PlaceholderView(icon: Icons.folder_off_rounded, text: "Der Ordner ist leer") : LoaderOverlay(
        child: RefreshIndicator(
          onRefresh: () {
            _query();
            return Future.delayed(const Duration(seconds: 3));
          },
          child: ListView.builder(
            itemCount: files.length,
            itemBuilder: (context, index) {
              CacheableFile file = files.toList()[index];
              return FileElement(file, widget.path, _query);
            },
          ),
        )
      )
    );
  }

  void mediaUpload(String? path) async {
    context.loaderOverlay.hide();

    if(path == null) {
      return;
    }

    var fileName = path.split(Platform.pathSeparator).last;
    showDialog(context: context, builder: (context) => FileUploadDialog(localPath: path, remotePath: widget.path, fileName: fileName, onUploadFinished: () => _query()), barrierDismissible: false);
  }
}
