import 'dart:convert';
import 'dart:io';

import 'package:app_hit_a_wod/src/blocs/user_edit_form.bloc.dart';
import 'package:app_hit_a_wod/src/models/user.model.dart';
import 'package:app_hit_a_wod/src/providers/api.provider.dart';
import 'package:image_picker/image_picker.dart';
import 'package:app_hit_a_wod/src/providers/auth.provider.dart';
import 'package:app_hit_a_wod/src/styles.dart';
import 'package:app_hit_a_wod/src/utils/fontello/my_flutter_app_icons.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:app_hit_a_wod/src/utils/custom_datepicker/datepicker_neu.dart';
import 'package:rxdart/rxdart.dart';

class UserDetailPage extends StatelessWidget {
  Widget build(BuildContext context) {
    final double formWidth = 80;
    final _api = Provider.of<ApiProvider>(context);
    final auth = Provider.of<AuthProvider>(context);
    final UserEditFormBloc bloc = UserEditFormBloc(user: auth.currentUser);

    return neuScaffoldDetail(
      context: context,
      title: Text("Editar perfil", style: Theme.of(context).textTheme.subhead.copyWith(fontWeight: FontWeight.w500, fontSize: 18)),
      action: FlatButton(
        child: Text("Guardar", style: Theme.of(context).textTheme.display1.copyWith(fontWeight: FontWeight.w500)),
        onPressed: () { 
          _save(context, bloc);
        }
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(20),
        child: Container(
          width: double.infinity,
          child: Column(
            children: _form(context, bloc, formWidth, _api),
          )
        )
      )
    );
  }

  _save(BuildContext context, UserEditFormBloc bloc) async {
    final AuthProvider _auth = Provider.of<AuthProvider>(context, listen: false);
    await _auth.updateUser(bloc.getUser());
    Navigator.pop(context);
  }

  List<Widget> _form(BuildContext context, UserEditFormBloc bloc, double width, ApiProvider _api) {
    return [
      _profilePhoto(context, bloc),
      SizedBox(height: 20),
      _editName(bloc, width),
      SizedBox(height: 20),
      _editSurnames(bloc, width),
      SizedBox(height: 20),
      _editDateOfBirth(bloc, width),
      SizedBox(height: 20),
      _editEmail(bloc, width),
      SizedBox(height: 20),
      _editPhone(bloc, width),
      SizedBox(height: 20),
      _editGender(bloc, width),
      SizedBox(height: 20),
      _editNif(bloc, width),
      SizedBox(height: 20),
      _editAddress(bloc, width),
      SizedBox(height: 20),
      _editZipcode(bloc, width),
      SizedBox(height: 20),
      _editPoblacio(bloc, width),
      SizedBox(height: 20),
      _editCountry(bloc, width, context),
      SizedBox(height: 20), 
      _editWeight(bloc, width),
      SizedBox(height: 20),
      _editHeight(bloc, width),
      SizedBox(height: 20),
      _changePasswordButton(context, bloc, _api),
      SizedBox(height: 20),
    ];
  }

  Widget _profilePhoto(BuildContext context, UserEditFormBloc bloc) {
    AuthProvider _auth = Provider.of<AuthProvider>(context);
    return StreamBuilder(
      stream: bloc.imageProfileUrlStream,
      builder: (BuildContext context, AsyncSnapshot<String> data) {
        if(data.hasData) {
          return Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Hero(
                    tag: 'edit-user-profile-image',
                    child: Container( 
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        image: DecorationImage(
                          fit: BoxFit.cover,
                          image: CachedNetworkImageProvider(data.data),
                        ),
                        boxShadow: [BoxShadow(
                          color: neuShadowDarkColor,
                          blurRadius: 10,
                          spreadRadius: -2,
                          offset: Offset(3.0, 3.0, )
                        )]
                      ),
                      width: 100,
                      height: 100
                    ),
                  ),
                  SizedBox(height: 10),
                  FlatButton(
                    child: Text("Cambiar foto de perfil", style: Theme.of(context).textTheme.display1.copyWith(fontWeight: FontWeight.w500)),
                    onPressed: () async {
                      File _image = await ImagePicker.pickImage(source: ImageSource.gallery);
                      User user = await _auth.updateUserProfileImage(_image);
                      bloc.setImageProfileUrl(user.url_profile_photo);
                    },
                  )
                ], 
              )
            ],
          );
        }
        else return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[ neuSkeletonCircle(100, 100) ],
        );
      } 
    );
  }

  Widget _editName(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.nameValue);
    return StreamBuilder(
      stream: bloc.nameStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Nombre", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Tu nombre',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setName
            )))
          ],
        );
      }
    );
  }

  Widget _editSurnames(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.surnamesValue);
    return StreamBuilder(
      stream: bloc.surnamesStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Apellidos", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Apellidos',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setSurnames
            )))
          ],
        );
      }
    );
  }

  Widget _editEmail(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.emailValue);
    return StreamBuilder(
      stream: bloc.emailStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Email", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.emailAddress,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Correo electrónico',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setEmail
            )))
          ],
        );
      }
    );
  }

  Widget _editPhone(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.phoneValue);
    return StreamBuilder(
      stream: bloc.phoneStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Teléfono", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.phone,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Tu teléfono de contacto',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setPhone
            )))
          ],
        );
      }
    );
  }

  Widget _editNif(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.nifValue);
    return StreamBuilder(
      stream: bloc.nifStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("NIF", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Tu DNI/NIF',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setNif
            )))
          ],
        );
      }
    );
  }

  Widget _editAddress(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.addressValue);
    return StreamBuilder(
      stream: bloc.addressStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Dirección", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              maxLines: 1,
              controller: ctrl,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Tu dirección',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setAddress
            )))
          ],
        );
      }
    );
  }

  Widget _editZipcode(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.zipcodeValue);
    return StreamBuilder(
      stream: bloc.zipcodeStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("C.P.", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.phone,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Código postal',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setZipcode
            )))
          ],
        );
      }
    );
  }

  Widget _editPoblacio(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.poblacioValue);
    return StreamBuilder(
      stream: bloc.poblacioStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Población", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Población',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: bloc.setPoblacio
            )))
          ],
        );
      }
    );
  }

  Widget _editWeight(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.weightValue!=null ? bloc.weightValue.toString() : null);
    return StreamBuilder(
      stream: bloc.weightStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Peso", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.number,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Peso',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                suffixText: "kg",
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.next,
              onChanged: (val) { bloc.setWeight(double.parse(val)); },
            )))
          ],
        );
      }
    );
  }

  Widget _editHeight(UserEditFormBloc bloc, double width) {
    TextEditingController ctrl = TextEditingController(text: bloc.heightValue!=null ? bloc.heightValue.toString() : null);
    return StreamBuilder(
      stream: bloc.heightStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return Row(
          children: <Widget>[
            SizedBox(child: Text("Altura", style: neuFormLabelStyle()), width: width),
            SizedBox(width: 15),
            Expanded(child: neuInput(TextFormField(
              controller: ctrl,
              keyboardType: TextInputType.number,
              decoration: InputDecoration(
                contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                border: InputBorder.none,
                hintText: 'Altura',
                errorText: snapshot.hasError ? snapshot.error.toString() : null,
                suffixText: "cm",
                errorStyle: TextStyle(color: colors["seven"])
              ),
              textInputAction: TextInputAction.send,
              onChanged: (val) { bloc.setHeight(double.parse(val)); },
            )))
          ],
        );
      }
    );
  }

  _editGender(UserEditFormBloc bloc, double width) {
    return StreamBuilder(
      stream: bloc.genderStream,
      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        if(!snapshot.hasData) {
          return Container();
        }
        else {
          return Row(
            children: <Widget>[
              SizedBox(child: Text("Género", style: neuFormLabelStyle()), width: width),
              SizedBox(width: 15),
              Expanded(child: NeumorphicToggle(
                style: NeumorphicToggleStyle(backgroundColor: neuColor, borderRadius: BorderRadius.circular(8)),
                height: 50.0,
                selectedIndex: snapshot.data=='M' ? 0 : (snapshot.data=='F' ? 2 : 1),
                displayForegroundOnlyIfSelected: true,
                children: [
                  ToggleElement(
                    background: Center( child: Icon(MyFlutterApp.male, size: 20), ),
                    foreground: Center( child: Icon(MyFlutterApp.male, color: colors["primary"], size: 20) )
                  ),
                  ToggleElement(
                    background: Center( child: Text("Otro/a") ),
                    foreground: Center( child: Text("Otro/a", style: TextStyle(color: colors["primary"], fontWeight: FontWeight.w500)) ),
                  ),
                  ToggleElement(
                    background: Center( child: Icon(MyFlutterApp.female, size: 20) ),
                    foreground: Center( child: Icon(MyFlutterApp.female, color: colors["primary"], size: 20) ),
                  ),
                ],
                thumb: Neumorphic(
                  style: neuStyle(),
                ),
                onChanged: (value) {
                  bloc.setGender(value==0 ? 'M' : (value==2 ? 'F' : 'O'));
                },
              ))
            ],
          );
        }
      }
    );
  }

  _editCountry(UserEditFormBloc bloc, double width, BuildContext context) {
    return FutureBuilder(
      future: DefaultAssetBundle.of(context).loadString("assets/country_codes.json"),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if(!snapshot.hasData) {
          return Container();
        }
        else {
          final List<dynamic> countries = json.decode(snapshot.data);
          return StreamBuilder(
            stream: bloc.countryStream,
            builder: (BuildContext context, AsyncSnapshot snapshotStream) {
              if(!snapshotStream.hasData) {
                return Container();
              }
              else {
                return Row(
                  children: <Widget>[
                    SizedBox(child: Text("País", style: neuFormLabelStyle()), width: width),
                    SizedBox(width: 15),
                    Expanded(child: neuContainer(
                      DropdownButton<String>(
                        isExpanded: true,
                        hint: Text("Selecciona pais"),
                        value: snapshotStream.data,
                        icon: Icon(Icons.arrow_drop_down, color: colors['primary'],),
                        underline: Container(height: 0, width: 0,),
                        items: countries.map((dynamic country) {
                          return new DropdownMenuItem<String>(
                            value: country['alpha_2'],
                            child: new Text(country['name'], overflow: TextOverflow.ellipsis),
                          );
                        }).toList(),
                        onChanged:  bloc.setCountry
                      ),
                      padding: EdgeInsets.symmetric(horizontal: 20, vertical: 7),
                    ))
                  ]
                );
              }
            }
          );
        }
      }
    );
    
  }

  _editDateOfBirth(UserEditFormBloc bloc, double width) {
    return StreamBuilder(
      stream: bloc.dateOfBirthStream,
      builder: (context, AsyncSnapshot<DateTime> snapshot) {
        if(!snapshot.hasData) return Container();
        else {
          return Row(
            children: <Widget>[
              SizedBox(width: width, child: Text("Edad", style: neuFormLabelStyle())),
              SizedBox(width: 15),
              Expanded(child: neuDatePicker(
                NeumorphicButton(
                  style: neuStylePressed(),
                  boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(neuRounded)),
                  padding: EdgeInsets.all(20), 
                  child: Container(
                    color: Colors.transparent,
                    child: Text(DateFormat('dd/MM/yyyy').format(snapshot.data)),
                  ),
                  onClick: () {
                    _selectDate(context, bloc);
                  }
                ),
              ))
            ],
          );
        }
      },
    );
  }

  Future<Null> _selectDate(BuildContext context, UserEditFormBloc bloc) async {
    final DateTime picked = await showNeuDatePicker(
      context: context,
      initialDate: bloc.dateOfBirthValue,
      firstDate: DateTime(1901),
      lastDate: DateTime.now(),
    );
    if (picked != null && picked != bloc.dateOfBirthValue) {
      bloc.setDateOfBirth(picked);
    }
  }

  _changePasswordButton(BuildContext context, UserEditFormBloc bloc, ApiProvider _api) {
    return neuButton(
      NeumorphicButton(
        boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(30)),
        padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
        style: NeumorphicStyle(
          color: colors['primary'],
          depth: neuDepth,
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(Icons.security, color: colors["white"], size: 20),
            SizedBox(width: 10),
            Text("Cambiar contraseña", style: Theme.of(context).textTheme.display2)
          ],
        ),
        onClick: () {
          _openChangePasswordDialog(context, bloc, _api);
        }
      ),
      borderRadius: BorderRadius.circular(30)
    );
  }

  void _openChangePasswordDialog(BuildContext context, UserEditFormBloc bloc, ApiProvider _api) {
    neuDialog(
      child: StreamBuilder(
        stream: CombineLatestStream.combine2(bloc.passwordStream, bloc.repeatPasswordStream, (a, b) => {"password": a, "repeat": b}),
        builder: (context, snapshot) {
          return Container(
            margin: EdgeInsets.all(5),
            child: Column(
              children: <Widget>[
                neuInput(TextFormField(
                  maxLines: 1,
                  obscureText: true,
                  keyboardType: TextInputType.visiblePassword,
                  decoration: InputDecoration(
                    contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                    border: InputBorder.none,
                    hintText: 'Contraseña',
                    errorText: snapshot.hasError ? snapshot.error.toString() : null,
                    errorStyle: TextStyle(color: colors["seven"])
                  ),
                  textInputAction: TextInputAction.send,
                  onChanged: bloc.setPassword,
                )),
                SizedBox(height: 20),
                neuInput(TextFormField(
                  maxLines: 1,
                  obscureText: true,
                  keyboardType: TextInputType.visiblePassword,
                  decoration: InputDecoration(
                    contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 5),
                    border: InputBorder.none,
                    hintText: 'Repite tu contraseña',
                  ),
                  textInputAction: TextInputAction.send,
                  onChanged: bloc.setRepeatPassword,
                )),
                SizedBox(height: 20),
                neuButton(
                  NeumorphicButton(
                    boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(30)),
                    padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
                    style: NeumorphicStyle(
                      color: colors['primary'],
                      depth: neuDepth,
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.security, color: colors["white"], size: 20),
                        SizedBox(width: 10),
                        Text("Cambiar contraseña", style: Theme.of(context).textTheme.display2)
                      ],
                    ),
                    onClick: () async {
                      if(snapshot.hasData && !snapshot.hasError && snapshot.data["password"] == snapshot.data["repeat"]) {
                        User user = await _api.updateUserPassword(bloc.id, snapshot.data["password"]);
                        Navigator.pop(context);
                      }
                    }
                  ),
                  borderRadius: BorderRadius.circular(30)
                )
              ],
            )
          );
        }
      ),
      context: context
    );
  }
}