// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

import 'use_cases/use_cases.dart';

void main() {
  runApp(const App());
  if (kIsWeb) {
    SemanticsBinding.instance.ensureSemantics();
  }
}

ThemeData _buildTheme({required Brightness brightness, double contrastLevel = 0.0}) {
  final scheme = ColorScheme.fromSeed(
    brightness: brightness,
    seedColor: const Color(0xff6750a4),
    contrastLevel: contrastLevel,
  );
  return ThemeData(
    colorScheme: scheme,
    appBarTheme: AppBarTheme(backgroundColor: scheme.primary, foregroundColor: scheme.onPrimary),
    pageTransitionsTheme: PageTransitionsTheme(
      builders: <TargetPlatform, PageTransitionsBuilder>{
        for (final TargetPlatform platform in TargetPlatform.values)
          platform: const FadeForwardsPageTransitionsBuilder(),
      },
    ),
  );
}

final ThemeData _lightTheme = _buildTheme(brightness: Brightness.light);
final ThemeData _darkTheme = _buildTheme(brightness: Brightness.dark);
final ThemeData _highContrastTheme = _buildTheme(brightness: Brightness.light, contrastLevel: 1.0);
final ThemeData _highContrastDarkTheme = _buildTheme(
  brightness: Brightness.dark,
  contrastLevel: 1.0,
);

class App extends StatelessWidget {
  const App({super.key, this.initialTags = const <Tag>{Tag.batch2}});

  final Set<Tag> initialTags;

  @override
  Widget build(BuildContext context) {
    final routes = Map<String, WidgetBuilder>.fromEntries(
      useCases.map(
        (UseCase useCase) => MapEntry<String, WidgetBuilder>(
          useCase.route,
          (BuildContext context) => useCase.buildWithTitle(context),
        ),
      ),
    );

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Accessibility Assessments Home Page',
      theme: _lightTheme,
      darkTheme: _darkTheme,
      highContrastTheme: _highContrastTheme,
      highContrastDarkTheme: _highContrastDarkTheme,
      routes: <String, WidgetBuilder>{
        '/': (_) => HomePage(initialTags: initialTags),
        ...routes,
      },
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key, required this.initialTags});

  final Set<Tag> initialTags;

  @override
  State<HomePage> createState() => HomePageState();
}

class HomePageState extends State<HomePage> {
  final ScrollController scrollController = ScrollController();

  late Set<Tag> _selectedTags;

  @override
  void initState() {
    super.initState();
    _selectedTags = Set<Tag>.from(widget.initialTags);
  }

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }

  Widget _buildUseCaseItem(int index, UseCase useCase) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: Builder(
        builder: (BuildContext context) {
          return TextButton(
            key: Key(useCase.name),
            onPressed: () =>
                Navigator.of(context).pushNamed(useCase.route, arguments: useCase.name),
            child: Text(useCase.name),
          );
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final List<UseCase> effectiveUseCases = useCases.where((UseCase useCase) {
      return _selectedTags.isEmpty || _selectedTags.every((Tag tag) => useCase.tags.contains(tag));
    }).toList();

    return Scaffold(
      appBar: AppBar(
        title: Semantics(headingLevel: 1, child: const Text('Accessibility Assessments')),
        actions: <Widget>[
          MenuAnchor(
            builder: (BuildContext context, MenuController controller, Widget? child) {
              return IconButton(
                tooltip: 'Filter by tags',
                icon: const Icon(Icons.filter_list),
                onPressed: () {
                  if (controller.isOpen) {
                    controller.close();
                  } else {
                    controller.open();
                  }
                },
              );
            },
            menuChildren: Tag.values.map((Tag tag) {
              return CheckboxMenuButton(
                closeOnActivate: false,
                value: _selectedTags.contains(tag),
                onChanged: (bool? value) {
                  setState(() {
                    if (value ?? false) {
                      _selectedTags.add(tag);
                    } else {
                      _selectedTags.remove(tag);
                    }
                  });
                },
                child: Tooltip(message: tag.description, child: Text(tag.name)),
              );
            }).toList(),
          ),
        ],
      ),
      body: Center(
        child: ListView(
          controller: scrollController,
          children: List<Widget>.generate(
            effectiveUseCases.length,
            (int index) => _buildUseCaseItem(index, effectiveUseCases[index]),
          ),
        ),
      ),
    );
  }
}
