// 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_settings.dart' show CroupierSettings, RandomSettings;

import 'package:flutter/material.dart';

typedef void NoArgCb();
typedef void OneStringCb(String data);
typedef void SaveDataCb(int userID, String jsonData);

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 CroupierSettings settings;
  final SaveDataCb saveDataCb;
  final NoArgCb backCb;

  CroupierSettingsComponent(this.settings, this.saveDataCb, 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.settings.name;
    _tempData[colorKey] = "${config.settings.color}";
    _tempData[avatarKey] = config.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(""), onPressed: cb));
  }

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

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

    Dialog dialog;
    NavigatorState navigator = Navigator.of(context);

    switch (dialogTypes[type]) {
      case DialogType.Text:
        dialog = new Dialog(
            title: new Text(capType),
            content: new Input(
                key: globalKeys[type],
                placeholder: capType,
                initialValue: config.settings.getStringValue(type),
                keyboardType: KeyboardType.TEXT,
                onChanged: _makeHandleChanged(type)),
            actions: [
              new FlatButton(child: new Text('CANCEL'), onPressed: () {
                navigator.pop();
              }),
              new FlatButton(child: new Text('SAVE'), onPressed: () {
                navigator.pop(_tempData[type]);
              }),
            ]);
        break;
      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}");
          }));
        }

        dialog = new Dialog(
            title: new Text(capType),
            content: new Grid(flexColors, maxChildExtent: 75.0),
            actions: [
              new FlatButton(child: new Text('CANCEL'), onPressed: () {
                navigator.pop();
              })
            ]);
        break;
      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);
          }));
        }

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

    showDialog(context: context, child: dialog)
        .then((String data) => _persist(type, data));
  }

  void _persist(String type, String data) {
    if (data == null) {
      return;
    }
    setState(() {
      config.settings.setStringValue(type, data);
      config.saveDataCb(config.settings.userID, config.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;
      });
    };
  }
}
