import 'dart:io' as io;

import 'package:aves/services/common/services.dart';
import 'package:aves/widgets/common/map/leaflet/vector_style_reader_extra.dart';
import 'package:flutter/material.dart';
import 'package:vector_map_tiles/src/io/io.dart' as vmtio show Directory; // ignore: implementation_imports
import 'package:vector_map_tiles/vector_map_tiles.dart';
import 'package:vector_tile_renderer/vector_tile_renderer.dart' as vtr;

class OsmLibertyLayer extends StatefulWidget {
  const OsmLibertyLayer({super.key});

  @override
  State<OsmLibertyLayer> createState() => _OsmLibertyLayerState();
}

class _OsmLibertyLayerState extends State<OsmLibertyLayer> {
  late final Future<TileProviders> _tileProviderFuture;
  late final Future<Style> _styleFuture;

  static const _openMapTileProviderSource = 'openmaptiles';

  // `Americana` provides tiles, but it uses layer syntax that is not supported by the vector tile renderer.
  // Full style is at 'https://americanamap.org/style.json' but it is heavy (1.0 MB, mostly for the layers).
  static const _americanaTileProviderUri = 'https://tile.ourmap.us/data/v3.json';

  // `OSM Liberty` is well supported by the vector tile renderer, but it requires an API key for the tiles.
  static const _osmLibertyStyleUri = 'https://maputnik.github.io/osm-liberty/style.json';

  // as of 2024/09/25,
  // Americana provider JSON:     39.4 kB
  // OSM Liberty style JSON:      48.3 kB
  // OSM Liberty sprites JSON 1x: 16.6 kB
  // OSM Liberty sprites  PNG 1x: 30.4 kB
  // OSM Liberty sprites JSON 2x: 16.6 kB
  // OSM Liberty sprites  PNG 2x: 82.5 kB
  // -> total overhead:          233.8 kB

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

    _tileProviderFuture = ExtraStyleReader.readProviderByName(
      {
        _openMapTileProviderSource: {
          'url': _americanaTileProviderUri,
          'type': 'vector',
        },
      },
    ).then(TileProviders.new);

    _styleFuture = StyleReader(
      uri: _osmLibertyStyleUri,
      logger: const vtr.Logger.console(),
    ).readExtra(skipSources: true);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<TileProviders>(
      future: _tileProviderFuture,
      builder: (context, tileProviderSnapshot) {
        return FutureBuilder<Style>(
          future: _styleFuture,
          builder: (context, styleSnapshot) {
            if (tileProviderSnapshot.hasError) return Text(tileProviderSnapshot.error.toString());
            if (styleSnapshot.hasError) return Text(styleSnapshot.error.toString());

            final tileProviders = tileProviderSnapshot.data;
            final style = styleSnapshot.data;
            if (tileProviders == null || style == null) return const SizedBox();

            return VectorTileLayer(
              tileProviders: tileProviders,
              theme: style.theme,
              sprites: style.sprites,
              // `vector` is higher quality and follows map orientation, but it is slower
              layerMode: VectorTileLayerMode.raster,
              cacheFolder: () async {
                final cacheRoot = await storageService.getExternalCacheDirectory();
                final path = pContext.join(cacheRoot, 'map_vector_tiles');
                dynamic result;
                if (vmtio.Directory == String) {
                  result = path;
                } else if (vmtio.Directory == io.Directory) {
                  result = io.Directory(path);
                } else {
                  throw Exception('vmtio.Directory type is not supported');
                }
                return result;
              },
            );
          },
        );
      },
    );
  }
}
