// Copyright 2019 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 'dart:math';

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

import '../logic/qualified_task.dart';
import '../logic/task_grid_filter.dart';
import '../model/commit.pb.dart';
import '../model/commit_status.pb.dart';
import '../model/task.pb.dart';
import '../state/build.dart';
import 'commit_box.dart';
import 'lattice.dart';
import 'task_box.dart';
import 'task_icon.dart';
import 'task_overlay.dart';

/// Container that manages the layout and data handling for [TaskGrid].
///
/// If there's no data for [TaskGrid], it shows [CircularProgressIndicator].
class TaskGridContainer extends StatelessWidget {
  const TaskGridContainer({super.key, this.filter, this.useAnimatedLoading = false});

  /// A notifier to hold a [TaskGridFilter] object to control the visibility of various
  /// rows and columns of the task grid. This filter may be updated dynamically through
  /// this notifier from elsewhere if the user starts editing the filter parameters in
  /// the settings dialog.
  final TaskGridFilter? filter;

  final bool useAnimatedLoading;

  @visibleForTesting
  static const String errorFetchCommitStatus = 'An error occurred fetching commit statuses';
  @visibleForTesting
  static const String errorFetchTreeStatus = 'An error occurred fetching tree build status';
  @visibleForTesting
  static const Duration errorSnackbarDuration = Duration(seconds: 8);

  @override
  Widget build(BuildContext context) {
    final BuildState buildState = Provider.of<BuildState>(context);
    return AnimatedBuilder(
      animation: buildState,
      builder: (BuildContext context, Widget? child) {
        final List<CommitStatus> commitStatuses = buildState.statuses;

        // Assume if there is no data that it is loading.
        if (commitStatuses.isEmpty) {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }

        return TaskGrid(
          buildState: buildState,
          commitStatuses: commitStatuses,
          filter: filter,
          useAnimatedLoading: useAnimatedLoading,
        );
      },
    );
  }
}

/// Display results from flutter/flutter repository's continuous integration.
///
/// Results are displayed in a matrix format. Rows are commits and columns
/// are the results from tasks.
class TaskGrid extends StatefulWidget {
  const TaskGrid({
    super.key,
    // TODO(ianh): We really shouldn't take both of these, since buildState exposes status as well;
    // it's asking for trouble because the tests can (and do) describe a mutually inconsistent state.
    required this.buildState,
    required this.commitStatuses,
    this.filter,
    this.useAnimatedLoading = false,
  });

  /// The build status data to display in the grid.
  final List<CommitStatus> commitStatuses;

  /// Reference to the build state to perform actions on [TaskMatrix], like rerunning tasks.
  final BuildState buildState;

  final bool useAnimatedLoading;

  /// A [TaskGridFilter] object to control the visibility of various rows and columns of
  /// the task grid. This filter may be updated dynamically from elsewhere if the user
  /// starts editing the filter parameters in the settings dialog.
  final TaskGridFilter? filter;

  @override
  State<TaskGrid> createState() => _TaskGridState();
}

/// Look up table for task status weights in the grid.
///
/// Weights should be in the range [0, 1.0] otherwise too much emphasis is placed on the first N rows, where N is the
/// largest integer weight.
const Map<String, double> _statusScores = <String, double>{
  'Failed - Rerun': 1.0,
  'Failed': 0.7,
  'Infra Failure - Rerun': 0.69,
  'Infra Failure': 0.68,
  'Failed - Flaky': 0.67,
  'Infra Failure - Flaky': 0.65,
  'In Progress - Flaky': 0.64,
  'New - Flaky': 0.63,
  'Succeeded - Flaky': 0.61,
  'New - Rerun': 0.5,
  'In Progress - Rerun': 0.4,
  'Unknown': 0.2,
  'In Progress': 0.1,
  'New': 0.1,
  'Succeeded': 0.01,
  'Skipped': 0.0,
};

class _TaskGridState extends State<TaskGrid> {
  // TODO(ianh): Cache the lattice cells. Right now we are regenerating the entire
  // lattice matrix each time the task grid has to update, regardless of whether
  // we've received new data or not.

  ScrollController? verticalController;
  ScrollController? horizontalController;

  @override
  void initState() {
    super.initState();
    verticalController ??= ScrollController();
    horizontalController ??= ScrollController();
    widget.filter?.addListener(() {
      setState(() {});
    });
  }

  @override
  void dispose() {
    verticalController?.dispose();
    horizontalController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return LatticeScrollView(
      // TODO(ianh): Provide some vertical scroll physics that disable
      // the clamping in the vertical direction, so that you can keep
      // scrolling past the end instead of hitting a wall every time
      // we load.
      // TODO(ianh): Trigger the loading from the scroll offset,
      // rather than the current hack of loading during build.
      cells: _processCommitStatuses(widget),
      verticalController: verticalController,
      horizontalController: horizontalController,
    );
  }

  /// This is the logic for turning the raw data from the [BuildState] object, a list of
  /// [CommitStatus] objects, into the data that describes the rendering as used by the
  /// [LatticeScrollView], a list of lists of [LatticeCell]s.
  ///
  /// The process is as follows:
  ///
  /// 1. We create `rows`, a list of [_Row] objects which are used to temporarily
  ///    represent each row in the data, where a row basically represents a [Commit].
  ///
  ///    These are derived from the `commitStatuses` directly -- each [CommitStatus] is one
  ///    row, representing one [Commit] and all its [Task]s.
  ///
  /// 2. We walk the `commitStatuses` again, examining each [Task] of each [CommitStatus],
  ///
  ///    For the first 25 rows, we compute a score for each task, one commit at a time, so
  ///    that we'll be able to sort the tasks later. The score is based on [_statusScores]
  ///    (the map defined above). Each row is weighted in the score proportional to how
  ///    far from the first row it is, so the first row has a weight of 1.0, the second a
  ///    weight of 1/2, the third a weight of 1/3, etc.
  ///
  ///    Then, we update the `rows` list to contain a [LatticeCell] for this task on this
  ///    commit. The color of the square is derived from [_painterFor], the builder, if
  ///    any, is derived from [_builderFor], and the tap handler from [_tapHandlerFor].
  ///
  /// 3. We create a list that represents all the tasks we've seen so far, sorted by
  ///    their score (tie-breaking on task names).
  ///
  /// 4. Finally, we generate the output, by putting together all the data collected in
  ///    the second step, walking the tasks in the order determined in the third step.
  //
  // TODO(ianh): Find a way to save the majority of the work done each time we build the
  // matrix. If you've scrolled down several thousand rows, you don't want to have to
  // rebuild the entire matrix each time you load another 25 rows.
  List<List<LatticeCell>> _processCommitStatuses(TaskGrid taskGrid) {
    TaskGridFilter? filter = taskGrid.filter;
    filter ??= TaskGridFilter();
    // 1: PREPARE ROWS
    final List<CommitStatus> filteredStatuses =
        taskGrid.commitStatuses.where((CommitStatus commitStatus) => filter!.matchesCommit(commitStatus)).toList();
    final List<_Row> rows =
        filteredStatuses.map<_Row>((CommitStatus commitStatus) => _Row(commitStatus.commit)).toList();
    // 2: WALK ALL TASKS
    final Map<QualifiedTask, double> scores = <QualifiedTask, double>{};
    final Map<QualifiedTask, Task> taskLookupMap = <QualifiedTask, Task>{};

    int commitCount = 0;
    for (final CommitStatus status in filteredStatuses) {
      commitCount += 1;
      for (final Task task in status.tasks) {
        final QualifiedTask qualifiedTask = QualifiedTask.fromTask(task);
        if (!filter.matchesTask(qualifiedTask)) {
          continue;
        }
        taskLookupMap[qualifiedTask] = task;
        if (commitCount <= 25) {
          String weightStatus = task.status;
          if (task.isFlaky || task.isTestFlaky) {
            // Flaky tasks should be shown after failures and reruns as they take up infra capacity.
            weightStatus += ' - Flaky';
          } else if (task.attempts > 1) {
            // Reruns take up extra infra capacity and should be prioritized.
            weightStatus += ' - Rerun';
          }
          // Make the score relative to how long ago it was run.
          final double score = _statusScores.containsKey(weightStatus)
              ? _statusScores[weightStatus]! / commitCount
              : _statusScores['Unknown']! / commitCount;
          scores.update(
            qualifiedTask,
            (double value) => value += score,
            ifAbsent: () => score,
          );
        } else {
          // In case we have a task that doesn't exist in the first 25 rows,
          // we still push the task into the table of scores. Otherwise, we
          // won't know how to sort the task later.
          scores.putIfAbsent(
            qualifiedTask,
            () => 0.0,
          );
        }
        rows[commitCount - 1].cells[qualifiedTask] = LatticeCell(
          painter: _painterFor(task),
          builder: _builderFor(task),
          onTap: _tapHandlerFor(status.commit, task),
        );
      }
    }
    // 3: SORT
    final List<QualifiedTask> tasks = scores.keys.toList()
      ..sort((QualifiedTask a, QualifiedTask b) {
        final int scoreComparison = scores[b]!.compareTo(scores[a]!);
        if (scoreComparison != 0) {
          return scoreComparison;
        }
        // If the scores are identical, break ties on the name of the task.
        // We do that because otherwise the sort order isn't stable.
        if (a.stage != b.stage) {
          return a.stage!.compareTo(b.stage!);
        }
        return a.task!.compareTo(b.task!);
      });

    // 4: GENERATE RESULTING LIST OF LISTS
    return <List<LatticeCell>>[
      <LatticeCell>[
        const LatticeCell(),
        ...tasks.map<LatticeCell>(
          (QualifiedTask task) =>
              LatticeCell(builder: (BuildContext context) => TaskIcon(qualifiedTask: task), taskName: task.stage),
        ),
      ],
      ...rows.map<List<LatticeCell>>(
        (_Row row) => <LatticeCell>[
          LatticeCell(
            builder: (BuildContext context) => CommitBox(commit: row.commit),
          ),
          ...tasks.map<LatticeCell>((QualifiedTask task) => row.cells[task] ?? const LatticeCell()),
        ],
      ),
      if (widget.buildState.moreStatusesExist) _generateLoadingRow(tasks.length),
    ];
  }

  Painter _painterFor(Task task) {
    final Paint backgroundPaint = Paint()..color = Theme.of(context).canvasColor;
    final Paint paint = Paint()
      ..color = TaskBox.statusColor.containsKey(task.status) ? TaskBox.statusColor[task.status]! : Colors.black;
    if (task.isFlaky) {
      paint.style = PaintingStyle.stroke;
      paint.strokeWidth = 2.0;
      return (Canvas canvas, Rect rect) {
        canvas.drawRect(rect.deflate(6.0), paint);
      };
    }
    return (Canvas canvas, Rect rect) {
      canvas.drawRect(rect.deflate(2.0), paint);
      if (task.attempts > 1 || task.isTestFlaky) {
        canvas.drawCircle(rect.center, (rect.shortestSide / 2.0) - 6.0, backgroundPaint);
      }
    };
  }

  WidgetBuilder? _builderFor(Task task) {
    if (task.attempts > 1 || task.isTestFlaky) {
      return (BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(4.0),
          child: Icon(Icons.priority_high, size: TaskBox.of(context) * 0.4),
        );
      };
    }
    return null;
  }

  static final List<String> _loadingMessage =
      'LOADING...'.runes.map<String>((int codepoint) => String.fromCharCode(codepoint)).toList();

  List<LatticeCell> _generateLoadingRow(int length) {
    return <LatticeCell>[
      LatticeCell(
        builder: (BuildContext context) {
          return FittedBox(
            fit: BoxFit.contain,
            child: Padding(
              padding: const EdgeInsets.all(12),
              child: widget.useAnimatedLoading
                  ? const RepaintBoundary(child: CircularProgressIndicator())
                  : const Icon(Icons.refresh),
            ),
          );
        },
      ),
      for (int index = 0; index < max(length, _loadingMessage.length); index++)
        LatticeCell(
          builder: (BuildContext context) {
            widget.buildState.fetchMoreCommitStatuses(); // This is safe to call many times.
            return Text(
              _loadingMessage[index % _loadingMessage.length],
              style: TextStyle(
                fontSize: TaskBox.of(context) * 0.9,
                fontWeight: FontWeight.w900,
              ),
              textAlign: TextAlign.center,
            );
          },
        ),
    ];
  }

  OverlayEntry? _taskOverlay;

  LatticeTapCallback _tapHandlerFor(Commit commit, Task task) {
    return (Offset? localPosition) {
      _taskOverlay?.remove();
      _taskOverlay = OverlayEntry(
        builder: (BuildContext context) => TaskOverlayEntry(
          position: (this.context.findRenderObject() as RenderBox)
              .localToGlobal(localPosition!, ancestor: Overlay.of(context).context.findRenderObject()),
          task: task,
          showSnackBarCallback: ScaffoldMessenger.of(context).showSnackBar,
          closeCallback: _closeOverlay,
          buildState: widget.buildState,
          commit: commit,
        ),
      );
      Overlay.of(context).insert(_taskOverlay!);
    };
  }

  void _closeOverlay() {
    _taskOverlay!.remove();
    _taskOverlay = null;
  }
}

class _Row {
  _Row(this.commit);
  final Commit commit;
  final Map<QualifiedTask, LatticeCell> cells = <QualifiedTask, LatticeCell>{};
}
