// Copyright 2015 The Chromium 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:sky/animation/animated_value.dart';
import 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/curves.dart';
import 'package:sky/base/lerp.dart';
import 'package:sky/painting/box_painter.dart';
import 'package:sky/painting/text_style.dart';
import 'package:sky/rendering/box.dart';
import 'package:sky/theme/colors.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/block_viewport.dart';
import 'package:sky/widgets/card.dart';
import 'package:sky/widgets/icon.dart';
import 'package:sky/widgets/scrollable.dart';
import 'package:sky/widgets/scaffold.dart';
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/tool_bar.dart';
import 'package:sky/widgets/framework.dart';
import 'package:sky/widgets/task_description.dart';

class CardModel {
  CardModel(this.value, this.height, this.color);
  int value;
  double height;
  Color color;
  String get label => "Card $value";
  Key get key => new Key.fromObjectIdentity(this);
}

class EnsureVisibleApp extends App {

  static const TextStyle cardLabelStyle =
    const TextStyle(color: white, fontSize: 18.0, fontWeight: bold);

  List<CardModel> cardModels;
  BlockViewportLayoutState layoutState = new BlockViewportLayoutState();
  ScrollListener scrollListener;
  ValueAnimation<double> scrollAnimation;

  void initState() {
    List<double> cardHeights = <double>[
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0
    ];
    cardModels = new List.generate(cardHeights.length, (i) {
      Color color = lerpColor(Red[300], Blue[900], i / cardHeights.length);
      return new CardModel(i, cardHeights[i], color);
    });

    scrollAnimation = new ValueAnimation<double>()
      ..duration = const Duration(milliseconds: 200)
      ..variable = new AnimatedValue<double>(0.0, curve: ease);

    super.initState();
  }

  EventDisposition handleTap(Widget target) {
    ensureWidgetIsVisible(target, animation: scrollAnimation);
    return EventDisposition.processed;
  }

  Widget builder(int index) {
    if (index >= cardModels.length)
      return null;
    CardModel cardModel = cardModels[index];
    Widget card = new Card(
      color: cardModel.color,
      child: new Container(
        height: cardModel.height,
        padding: const EdgeDims.all(8.0),
        child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
      )
    );
    return new Listener(
      key: cardModel.key,
      onGestureTap: (_) { return handleTap(card); },
      child: card
    );
  }

  Widget build() {
    Widget cardCollection = new Container(
      padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0),
      decoration: new BoxDecoration(backgroundColor: Theme.of(this).primarySwatch[50]),
      child: new VariableHeightScrollable(
        builder: builder,
        token: cardModels.length,
        layoutState: layoutState
      )
    );

    return new IconTheme(
      data: const IconThemeData(color: IconThemeColor.white),
      child: new Theme(
        data: new ThemeData(
          brightness: ThemeBrightness.light,
          primarySwatch: Blue,
          accentColor: RedAccent[200]
        ),
        child: new TaskDescription(
          label: 'Cards',
          child: new Scaffold(
            toolbar: new ToolBar(center: new Text('Tap a Card')),
            body: cardCollection
          )
        )
      )
    );
  }
}

void main() {
  runApp(new EnsureVisibleApp());
}
