// Copyright 2017 The Fuchsia 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:fidl_fuchsia_modular/fidl.dart';
import 'package:flutter/widgets.dart';

import '../models/layout_model.dart';
import '../models/surface/positioned_surface.dart';
import '../models/surface/surface.dart';
import '../models/surface/surface_graph.dart';
import '../models/tree/spanning_tree.dart';
import '../models/tree/tree.dart';

// Convenience comparator used to ensure more focused items get higher priority
int _compareByOtherList(Surface l, Surface r, List<Surface> otherList) {
  int li = otherList.indexOf(l);
  int ri = otherList.indexOf(r);
  if (li < 0) {
    li = otherList.length;
  }
  if (ri < 0) {
    ri = otherList.length;
  }
  return ri - li;
}

/// Returns in the order they should be stacked
List<PositionedSurface> layoutSurfaces(
  BuildContext context,
  SurfaceGraph graph,
  List<Surface> focusStack,
  LayoutModel layoutModel,
) {
  Surface focused = focusStack.lastWhere((Surface surface) {
    return surface.connection != null;
  }, orElse: () => null);
  if (focusStack.isEmpty || focused == null) {
    return <PositionedSurface>[];
  }
  SurfaceArrangement focusedArrangement = focused.relation.arrangement;

  Tree<Surface> copresTree = getCopresentSpanningTree(focused);

  // Ontop only applies if the currently focused mod has a parent. If there's
  // only one sutface in the stack, fall through to the logic below.
  if (focusedArrangement == SurfaceArrangement.ontop && focusStack.length > 1) {
    // Determine the parent's position and then place the focused surface on top.
    List<PositionedSurface> surfaces = layoutSurfaces(context, graph,
        focusStack.sublist(0, focusStack.length - 1), layoutModel);
    PositionedSurface parentSurface =
        surfaces.firstWhere((PositionedSurface positioned) {
      return positioned.surface == focused.parent;
    });
    PositionedSurface ontopSurface = new PositionedSurface(
      surface: focused,
      position: parentSurface.position,
    );
    surfaces.add(ontopSurface);
    return surfaces;
  }

  int focusOrder(Tree<Surface> l, Tree<Surface> r) =>
      _compareByOtherList(l.value, r.value, focusStack);

  // Remove dismissed surfaces and surfaces without views and collapse tree
  for (Tree<Surface> node in copresTree) {
    if (node.value.dismissed || node.value.connection == null) {
      node.children.forEach(node.parent.add);
      node.detach();
    }
  }

  // Prune less focused surfaces where their min constraints do not fit
  double totalMinWidth = 0.0;
  for (Tree<Surface> node
      in copresTree.flatten(orderChildren: focusOrder).skipWhile(
    (Tree<Surface> node) {
      double minWidth = node.value.minWidth(min: layoutModel.minScreenRatio);
      if (totalMinWidth + minWidth > 1.0) {
        return false;
      }
      totalMinWidth += minWidth;
      return true;
    },
  )) {
    node.detach();
  }

  // Prune less focused surfaces where emphasis values cannot be respected
  double totalEmphasis = 0.0;
  Surface top = focused;
  Surface tightestFit = focused;
  for (Tree<Surface> node
      in copresTree.flatten(orderChildren: focusOrder).skipWhile(
    (Tree<Surface> node) {
      Surface prevTop = top;
      double prevTotalEmphasis = totalEmphasis;

      // Update top
      if (top.ancestors.contains(node.value)) {
        top = node.value;
        totalEmphasis *= prevTop.absoluteEmphasis(top);
      }
      double emphasis = node.value.absoluteEmphasis(top);
      totalEmphasis += emphasis;

      // Calculate min width available
      double tightestFitEmphasis = tightestFit.absoluteEmphasis(top);
      double extraWidth = emphasis / totalEmphasis -
          node.value.minWidth(min: layoutModel.minScreenRatio);
      double tightestFitExtraWidth = tightestFitEmphasis / totalEmphasis -
          tightestFit.minWidth(min: layoutModel.minScreenRatio);

      // Break if smallest or this doesn't fit
      if (min(tightestFitExtraWidth, extraWidth) < 0.0) {
        // Restore previous values
        top = prevTop;
        totalEmphasis = prevTotalEmphasis;
        return false;
      }

      // Update tightest fit
      if (extraWidth < tightestFitExtraWidth) {
        tightestFit = node.value;
      }
      return true;
    },
  )) {
    node.detach();
  }

  List<Surface> surfacesToDisplay =
      copresTree.map((Tree<Surface> t) => t.value).toList(growable: false);

  Iterable<Surface> arrangement =
      top.flattened.where((Surface s) => surfacesToDisplay.contains(s));

  // Layout rects for arrangement
  final List<PositionedSurface> layout = <PositionedSurface>[];
  double fractionalWidthOffset = 0.0;
  for (Surface surface in arrangement) {
    double fractionalWidth = surface.absoluteEmphasis(top) / totalEmphasis;
    double fractionalHeight = 1.0;
    layout.add(
      new PositionedSurface(
        surface: surface,
        position: new Rect.fromLTWH(
          fractionalWidthOffset,
          0.0,
          fractionalWidth,
          fractionalHeight,
        ),
      ),
    );
    fractionalWidthOffset += fractionalWidth;
  }
  return layout;
}
