// Copyright 2015 The Vanadium 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 '../logic/croupier.dart' as logic_croupier;
import '../logic/croupier_settings.dart' show CroupierSettings, RandomSettings;

import 'package:sky/widgets_next.dart';

typedef void NoArgCb();
typedef void OneStringCb(String data);

enum DialogType {
  Text, ColorPicker, ImagePicker
}

const String nameKey = "name";
const String colorKey = "color";
const String avatarKey = "avatar";

Map<String, GlobalKey> globalKeys = {
  nameKey: new GlobalKey(),
  colorKey: new GlobalKey(),
  avatarKey: new GlobalKey()
};

Map<String, DialogType> dialogTypes = {
  nameKey: DialogType.Text,
  colorKey: DialogType.ColorPicker,
  avatarKey: DialogType.ImagePicker
};

class CroupierSettingsComponent extends StatefulComponent {
  final NavigatorState navigator;
  final logic_croupier.Croupier croupier;
  final NoArgCb backCb;

  CroupierSettingsComponent(this.navigator, this.croupier, this.backCb);

  CroupierSettingsComponentState createState() => new CroupierSettingsComponentState();
}

class CroupierSettingsComponentState extends State<CroupierSettingsComponent> {
  Map<String, String> _tempData = new Map<String, String>();

  void initState(_) {
    super.initState(_);

    _initializeTemp();
  }

  void _initializeTemp() {
    _tempData[nameKey] = config.croupier.settings.name;
    _tempData[colorKey] = "${config.croupier.settings.color}";
    _tempData[avatarKey] = config.croupier.settings.avatar;
  }

  Widget _makeColoredRectangle(int colorInfo, String text, NoArgCb cb) {
    return new Container(
          decoration: new BoxDecoration(
                backgroundColor: new Color(colorInfo)),
          child: new FlatButton(child: new Text(""), enabled: cb != null,
            onPressed: cb));
  }

  Widget _makeImageButton(String url, NoArgCb cb) {
    return new FlatButton(child: new NetworkImage(src: url), enabled: cb != null, onPressed: cb);
  }

  Widget build(BuildContext context) {
    List<Widget> w = new List<Widget>();
    w.add(_makeButtonRow(nameKey, new Text(config.croupier.settings.name)));
    w.add(_makeButtonRow(colorKey, _makeColoredRectangle(config.croupier.settings.color, "", null)));
    w.add(_makeButtonRow(avatarKey, new NetworkImage(src: config.croupier.settings.avatar)));

    w.add(new FlatButton(child: new Text("Return"), onPressed: config.backCb));
    return new Column(w);
  }

  Widget _makeButtonRow(String type, Widget child) {
    String capType = _capitalize(type);
    return new FlatButton(
      onPressed: () => _handlePressed(type),
      child: new Row([
        new Flexible(flex: 1, child: new Text(capType, style: Theme.of(context).text.subhead)),
        new Flexible(flex: 3, child: child)
      ], justifyContent: FlexJustifyContent.start)
    );
  }

  void _handlePressed(String type) {
    var capType = _capitalize(type);
    showDialog(config.navigator, (NavigatorState navigator) {
      switch (dialogTypes[type]) {
        case DialogType.Text:
          return new Dialog(
            title: new Text(capType),
            content: new Input(
              key: globalKeys[type],
              placeholder: capType,
              initialValue: config.croupier.settings.getStringValue(type),
              keyboardType: KeyboardType.TEXT,
              onChanged: _makeHandleChanged(type)
            ),
            onDismiss: () {
              navigator.pop();
            },
            actions: [
              new FlatButton(
                child: new Text('CANCEL'),
                onPressed: () {
                  navigator.pop();
                }
              ),
              new FlatButton(
                child: new Text('SAVE'),
                onPressed: () {
                  navigator.pop(_tempData[type]);
                }
              ),
            ]
          );
        case DialogType.ColorPicker:
          List<Widget> flexColors = new List<Widget>();
          List<int> colors = <int>[
            0xcfefefef,
            0xcfff3333,
            0xcf33ff33,
            0xcf3333ff,
            0xcf101010,
            0xcf33ffff,
            0xcfff33ff,
            0xcfffff33,
          ];
          for (int i = 0; i < colors.length; i++) {
            int c = colors[i];
            flexColors.add(_makeColoredRectangle(c, "", () {
              // TODO(alexfandrianto): Remove this hack-y subtraction once the
              // Dart + Android issue with int.parse is fixed.
              navigator.pop("${c - 0xcf000000}");
            }));
          }

          return new Dialog(
            title: new Text(capType),
            content: new Grid(flexColors, maxChildExtent: 75.0),
            onDismiss: () {
              navigator.pop();
            },
            actions: [
              new FlatButton(
                child: new Text('CANCEL'),
                onPressed: () {
                  navigator.pop();
                }
              )
            ]
          );
        case DialogType.ImagePicker:
          List<Widget> flexAvatars = new List<Widget>();
          for (int i = 0; i < RandomSettings.avatars.length; i++) {
            String avatar = RandomSettings.avatars[i];
            flexAvatars.add(_makeImageButton(avatar, () {
              navigator.pop(avatar);
            }));
          }

          return new Dialog(
            title: new Text(capType),
            content: new Grid(flexAvatars, maxChildExtent: 75.0),
            onDismiss: () {
              navigator.pop();
            },
            actions: [
              new FlatButton(
                child: new Text('CANCEL'),
                onPressed: () {
                  navigator.pop();
                }
              )
            ]
          );
        default:
          assert(false);
          return null;
      }

    }).then((String data) => _persist(type, data));
  }

  void _persist(String type, String data) {
    if (data == null) {
      return;
    }
    setState(() {
      config.croupier.settings.setStringValue(type, data);
      config.croupier.settings_manager.save(config.croupier.settings.userID, config.croupier.settings.toJSONString());
    });
  }

  String _capitalize(String s) => s[0].toUpperCase() + s.substring(1);

  OneStringCb _makeHandleChanged(String type) {
    return (String data) {
      setState(() {
        print("Updating ${type} with ${data}");
        _tempData[type] = data;
      });
    };
  }
}