// 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:async';
import 'dart:math';

import 'package:cocoon_common/is_dart_internal.dart';
import 'package:cocoon_common/rpc_model.dart';
import 'package:cocoon_common/task_status.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../logic/qualified_task.dart';
import '../logic/task_grid_filter.dart';
import '../state/build.dart';
import 'commit_box.dart';
import 'lattice.dart';
import 'task_box.dart';
import 'task_icon.dart';
import 'task_overlay.dart';
import 'test_details_popover.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,
    this.schedulePostsubmitBuildForReleaseBranch,
  });

  /// 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 Future<void> Function(Commit commit)?
  schedulePostsubmitBuildForReleaseBranch;

  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 = Provider.of<BuildState>(context);
    return AnimatedBuilder(
      animation: buildState,
      builder: (BuildContext context, Widget? child) {
        final commitStatuses = buildState.statuses;

        if (commitStatuses.isEmpty) {
          if (buildState.moreStatusesExist) {
            return const Center(child: CircularProgressIndicator());
          } else {
            return const Center(child: Text('No commits found.'));
          }
        }

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

/// 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.schedulePostsubmitBuildForReleaseBranch,
    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 Future<void> Function(Commit commit)?
  schedulePostsubmitBuildForReleaseBranch;

  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>{
  'Release Builder': 1.0,
  'Failed - Rerun': 1.0,
  'In Progress - Broke Tree': 0.7,
  '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) {
    var filter = taskGrid.filter;
    filter ??= TaskGridFilter();

    // Pre-compute suppressed task names for faster lookup
    final suppressedTasks = {
      for (final s in taskGrid.buildState.suppressedTests) s.name: s,
    };

    // 1: PREPARE ROWS
    final filteredStatuses = taskGrid.commitStatuses
        .where(
          (CommitStatus commitStatus) => filter!.matchesCommit(commitStatus),
        )
        .toList();
    final rows = filteredStatuses
        .map<_Row>((CommitStatus commitStatus) => _Row(commitStatus.commit))
        .toList();
    // 2: WALK ALL TASKS
    final scores = <QualifiedTask, double>{};
    final taskLookupMap = <QualifiedTask, Task>{};

    var commitCount = 0;
    for (final status in filteredStatuses) {
      commitCount += 1;
      for (final task in status.tasks) {
        final qualifiedTask = QualifiedTask.fromTask(task);
        if (!filter.matchesTask(qualifiedTask)) {
          continue;
        }
        taskLookupMap[qualifiedTask] = task;
        if (commitCount <= 25) {
          var weightStatus = task.status.value;
          if (isTaskFromDartInternalBuilder(builderName: task.builderName)) {
            weightStatus = 'Release Builder';
          } else if (task.lastAttemptFailed) {
            weightStatus += ' - Broke Tree';
          } else if (task.isBringup) {
            // Flaky tasks should be shown after failures and reruns as they take up infra capacity.
            weightStatus += ' - Flaky';
          } else if (task.isFlaky) {
            // Reruns take up extra infra capacity and should be prioritized.
            weightStatus += ' - Rerun';
          }
          // Make the score relative to how long ago it was run.
          final 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);
        }
        final isSuppressed = suppressedTasks.containsKey(task.builderName);
        rows[commitCount - 1].cells[qualifiedTask] = LatticeCell(
          painter: _painterFor(task, isSuppressed),
          builder: _builderFor(task, isSuppressed),
          onTap: _tapHandlerFor(status.commit, task),
        );
      }
    }
    // 3: SORT
    final tasks = scores.keys.toList()
      ..sort((QualifiedTask a, QualifiedTask b) {
        // Suppressed tests go first (far left)
        final aSuppressed = suppressedTasks.containsKey(a.task);
        final bSuppressed = suppressedTasks.containsKey(b.task);
        if (aSuppressed && !bSuppressed) {
          return -1;
        }
        if (!aSuppressed && bSuppressed) {
          return 1;
        }

        final scoreComparison = scores[b]!.compareTo(scores[a]!);
        if (scoreComparison != 0) {
          return scoreComparison;
        }
        return a.task.compareTo(b.task);
      });

    // 4: GENERATE RESULTING LIST OF LISTS
    return <List<LatticeCell>>[
      <LatticeCell>[
        const LatticeCell(),
        ...tasks.map<LatticeCell>((QualifiedTask task) {
          return LatticeCell(
            builder: (BuildContext context) {
              final suppressedTest = suppressedTasks[task.task];
              final icon = TaskIcon(
                qualifiedTask: task,
                onTap: (BuildContext context) =>
                    _showTestDetails(context, task),
              );
              if (suppressedTest != null) {
                // Format audit log
                return Stack(
                  alignment: Alignment.bottomRight,
                  children: [
                    Opacity(opacity: 0.3, child: icon),
                    const IgnorePointer(
                      child: Icon(
                        Icons.snooze,
                        fontWeight: FontWeight.bold,
                        size: 20,
                        color: Colors.red,
                      ),
                    ),
                  ],
                );
              }
              return icon;
            },
            taskName: task.task,
          );
        }),
      ],
      ...rows.map<List<LatticeCell>>(
        (_Row row) => <LatticeCell>[
          LatticeCell(
            builder: (BuildContext context) => CommitBox(
              commit: row.commit,
              schedulePostsubmitBuild: () {
                if (widget.schedulePostsubmitBuildForReleaseBranch
                    case final schedule?) {
                  return () async => schedule(row.commit);
                }
                return null;
              }(),
            ),
          ),
          ...tasks.map<LatticeCell>(
            (QualifiedTask task) => row.cells[task] ?? const LatticeCell(),
          ),
        ],
      ),
      if (widget.buildState.moreStatusesExist)
        _generateLoadingRow(tasks.length),
    ];
  }

  Painter _painterFor(Task task, bool isSuppressed) {
    final backgroundPaint = Paint()..color = Theme.of(context).canvasColor;

    assert(
      TaskBox.statusColor.containsKey(task.status),
      'Unknown or unexpected status: ${task.status}',
    );

    var color = TaskBox.statusColor.containsKey(task.status)
        ? TaskBox.statusColor[task.status]!
        : Colors.transparent;
    if (task.status == TaskStatus.inProgress) {
      if (task.lastAttemptFailed) {
        color = TaskBox.statusColorFailedAndRerunning;
      } else if (task.currentBuildNumber == null) {
        color = TaskBox.statusColorInProgressButQueued;
      }
    }

    // Apply "Ghost Mode" for suppressed tests
    if (isSuppressed) {
      // Apply "ghost mode" to the color.
      color = color.withValues(alpha: 0.5);
    }

    final paint = Paint()..color = color;
    if (task.isBringup) {
      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.isFlaky) {
        canvas.drawCircle(
          rect.center,
          (rect.shortestSide / 2.0) - 6.0,
          backgroundPaint,
        );
      }
    };
  }

  WidgetBuilder? _builderFor(Task task, bool isSuppressed) {
    if (task.isFlaky) {
      return (BuildContext context) {
        final icon = Padding(
          padding: const EdgeInsets.all(4.0),
          child: Icon(Icons.priority_high, size: TaskBox.of(context) * 0.4),
        );
        return isSuppressed ? Opacity(opacity: 0.5, child: icon) : icon;
      };
    }
    if (task.status == TaskStatus.skipped) {
      return (BuildContext context) {
        final icon = Padding(
          padding: const EdgeInsets.all(4.0),
          child: Icon(Icons.network_ping, size: TaskBox.of(context) * 0.6),
        );
        return isSuppressed ? Opacity(opacity: 0.5, child: icon) : icon;
      };
    }
    return null;
  }

  static final List<String> _loadingMessage = 'LOADING...'.runes
      .map<String>(String.fromCharCode)
      .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) {
            unawaited(
              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 _showTestDetails(BuildContext context, QualifiedTask task) {
    _taskOverlay?.remove();

    final renderBox = context.findRenderObject() as RenderBox;
    final position = renderBox.localToGlobal(Offset.zero);

    print('_showTestDetails: $position');
    _taskOverlay = OverlayEntry(
      builder: (BuildContext context) => Stack(
        children: <Widget>[
          GestureDetector(
            onTap: _closeOverlay,
            behavior: HitTestBehavior.opaque,
            child: const SizedBox.expand(),
          ),
          Positioned(
            child: CustomSingleChildLayout(
              delegate: TaskOverlayEntryPositionDelegate(
                position,
                cellSize: TaskBox.of(context),
              ),
              child: TestDetailsPopover(
                qualifiedTask: task,
                buildState: widget.buildState,
                showSnackBarCallback: ScaffoldMessenger.of(
                  context,
                ).showSnackBar,
                closeCallback: _closeOverlay,
              ),
            ),
          ),
        ],
      ),
    );
    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>{};
}
