// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. 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:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';

String flutterPkgLibPath = '/packages/flutter/lib';

/**
 * Add some Flutter libraries and types to the given [provider] and return
 * the `lib` folder.
 */
Folder configureFlutterPackage(MemoryResourceProvider provider) {
  File newFile(String path, String content) =>
      provider.newFile(provider.convertPath(path), content ?? '');

  Folder newFolder(String path) =>
      provider.newFolder(provider.convertPath(path));

  newFile('$flutterPkgLibPath/material.dart', r'''
export 'widgets.dart';
export 'src/material/app_bar.dart';
export 'src/material/gesture_detector.dart';
export 'src/material/icons.dart';
export 'src/material/scaffold.dart';
''');

  newFile('$flutterPkgLibPath/widgets.dart', r'''
export 'src/widgets/basic.dart';
export 'src/widgets/container.dart';
export 'src/widgets/framework.dart';
export 'src/widgets/icon.dart';
export 'src/widgets/text.dart';
''');

  newFile('$flutterPkgLibPath/foundation.dart', r'''
export 'package:meta/meta.dart' show
  required;

export 'src/foundation/key.dart';
''');

  void createSrcMaterial() {
    newFile('$flutterPkgLibPath/src/material/app_bar.dart', r'''
import 'package:flutter/widgets.dart';

class AppBar extends StatefulWidget {
  AppBar({
    Key key,
    title,
    backgroundColor,
  });
}
''');

    newFile('$flutterPkgLibPath/src/material/icons.dart', r'''
import 'package:flutter/widgets.dart';

class Icons {
  static const IconData alarm =
      const IconData(0xe855, fontFamily: 'MaterialIcons');
  static const IconData book =
      const IconData(0xe865, fontFamily: 'MaterialIcons');
  Icons._();
}
''');

    newFile('$flutterPkgLibPath/src/material/scaffold.dart', r'''
import 'package:flutter/widgets.dart';

class Scaffold extends StatefulWidget {
  const Scaffold({
    Key key,
    Widget body,
  });
}
''');

    newFile('$flutterPkgLibPath/src/material/gesture_detector.dart', r'''
import 'package:flutter/widgets.dart';

class GestureDetector extends StatelessWidget {
  GestureDetector({
    Key key,
    Widget child,
    onTap,
  });
}
''');
  }

  void createRendering() {
    newFile('$flutterPkgLibPath/rendering.dart', r'''
export 'painting.dart';
export 'src/rendering/flex.dart';
''');
    newFile('$flutterPkgLibPath/src/rendering/flex.dart', r'''
enum CrossAxisAlignment {
  start,
  end,
  center,
  stretch,
  baseline,
}
''');
  }

  void createPainting() {
    newFile('$flutterPkgLibPath/painting.dart', r'''
export 'src/painting/edge_insets.dart';
''');

    newFile('$flutterPkgLibPath/src/painting/edge_insets.dart', r'''
abstract class EdgeInsetsGeometry {
  const EdgeInsetsGeometry();
}

class EdgeInsets extends EdgeInsetsGeometry {
  const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);

  const EdgeInsets.all(double value)
      : left = value, top = value, right = value, bottom = value;

  const EdgeInsets.only({
    this.left: 0.0,
    this.top: 0.0,
    this.right: 0.0,
    this.bottom: 0.0
  });

  const EdgeInsets.symmetric({ double vertical: 0.0,
                             double horizontal: 0.0 })
    : left = horizontal, top = vertical, right = horizontal, bottom = vertical;
}
''');
  }

  void createSrcFoundation() {
    newFile('$flutterPkgLibPath/src/foundation/key.dart', r'''

abstract class Key {
  const factory Key(String value) = ValueKey<String>;

  const Key._();
}

abstract class LocalKey extends Key {
  const LocalKey() : super._();
}


class ValueKey<T> extends LocalKey {
  final T value;

  const ValueKey(this.value);
}
''');
  }

  void createSrcWidgets() {
    newFile('$flutterPkgLibPath/src/widgets/basic.dart', r'''
import 'package:flutter/rendering.dart';

import 'framework.dart';

export 'package:flutter/painting.dart';
export 'package:flutter/rendering.dart';

class Center extends StatelessWidget {
  const Center({Key key, double heightFactor, Widget child});
}

class Column extends Flex {
  Column({
    Key key,
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
    List<Widget> children: const <Widget>[],
  });
}

class Row extends Flex {
  Row({
    Key key,
    List<Widget> children: const <Widget>[],
  });
}

class Flex extends Widget {
  Flex({
    Key key,
    List<Widget> children: const <Widget>[],
  });
}

class ClipRect extends SingleChildRenderObjectWidget {
  const ClipRect({Key key, Widget child}) :
    super(key: key, child: child);
    
  /// Does not actually exist in Flutter.
  const ClipRect.rect({Key key, Widget child}) :
    super(key: key, child: child);
}

class Transform extends SingleChildRenderObjectWidget {
  const Transform({
    Key key,
    @required transform,
    origin,
    alignment,
    transformHitTests: true,
    Widget child,
  });
}

class AspectRatio extends SingleChildRenderObjectWidget {
  const AspectRatio({
    Key key,
    @required double aspectRatio,
    Widget child,
  });
}

class Padding extends SingleChildRenderObjectWidget {
  final EdgeInsetsGeometry padding;

  const Padding({
    Key key,
    this.padding,
    Widget child,
  });
}

class Expanded extends StatelessWidget {
  const Expanded({
    Key key,
    int flex: 1,
    @required Widget child,
  });
}
''');

    newFile('$flutterPkgLibPath/src/widgets/container.dart', r'''
import 'framework.dart';

class Container extends StatelessWidget {
  final Widget child;
  Container({
    Key key,
    double width,
    double height,
    this.child,
  })
      : super(key: key);

  @override
  Widget build(BuildContext context) => child;
}
''');

    newFile('$flutterPkgLibPath/src/widgets/framework.dart', r'''
import 'package:flutter/foundation.dart';

export 'package:flutter/foundation.dart' show required;
export 'package:flutter/foundation.dart' show Key, LocalKey, ValueKey;

typedef void VoidCallback();

abstract class BuildContext {
  Widget get widget;
}

abstract class State<T extends StatefulWidget> {
  BuildContext get context => null;

  T get widget => null;

  Widget build(BuildContext context) {}

  void dispose() {}

  void setState(VoidCallback fn) {}
}

abstract class StatefulWidget extends Widget {
  const StatefulWidget({Key key}) : super(key: key);

  State createState() => null
}

abstract class StatelessWidget extends Widget {
  const StatelessWidget({Key key}) : super(key: key);

  Widget build(BuildContext context) => null;
}

class Widget {
  final Key key;

  const Widget({this.key});
}

abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
  final Widget child;

  const SingleChildRenderObjectWidget({Key key, this.child}) : super(key: key);
}

abstract class RenderObjectWidget extends Widget {
  const RenderObjectWidget({Key key}) : super(key: key);
}
''');

    newFile('$flutterPkgLibPath/src/widgets/icon.dart', r'''
import 'framework.dart';

class Icon extends StatelessWidget {
  final IconData icon;
  const Icon(
    this.icon, {
    Key key,
  })
      : super(key: key);
}

class IconData {
  final int codePoint;
  final String fontFamily;
  const IconData(
    this.codePoint, {
    this.fontFamily,
  });
}
''');

    newFile('$flutterPkgLibPath/src/widgets/text.dart', r'''
import 'framework.dart';

class DefaultTextStyle extends StatelessWidget {
  DefaultTextStyle({Widget child});
}

class Text extends StatelessWidget {
  final String data;
  const Text(
    this.data, {
    Key key,
  })
      : super(key: key);
}
''');
  }

  createSrcFoundation();
  createPainting();
  createRendering();
  createSrcWidgets();
  createSrcMaterial();

  return newFolder(flutterPkgLibPath);
}
