import 'dart:convert';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'dart:math' as math;
import 'dart:html' as html;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:memorias_calculo_web/src/providers/pdf_provider.dart';
import 'package:memorias_calculo_web/src/widgets/encabezado_pais.dart';
import 'package:memorias_calculo_web/src/widgets/formatters.dart';

class CalculadoraEstacionamientoPage extends StatefulWidget {
  final String ciudad;
  final String estado;
  final String pais;
  final String code;
  final String idProyecto;
  final String idUsuario;
  final String token;
  final String datos;
  final String noProyecto;
  final String archpdf;

  const CalculadoraEstacionamientoPage({
    Key? key,
    required this.ciudad,
    required this.estado,
    required this.pais,
    required this.code,
    required this.idProyecto,
    required this.idUsuario,
    required this.token,
    required this.datos,
    required this.noProyecto,
    required this.archpdf,
  }) : super(key: key);

  @override
  State<CalculadoraEstacionamientoPage> createState() => _CalculadoraEstacionamientoPageState();
}

class _CalculadoraEstacionamientoPageState extends State<CalculadoraEstacionamientoPage> {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  final TextEditingController _areaController = TextEditingController(text: "0.00");
  final TextEditingController _alturaController = TextEditingController(text: "0.00");
  final TextEditingController _distMaxController = TextEditingController(text: "0.00");
  final TextEditingController _nivelesController = TextEditingController(text: "1");
  final TextEditingController _tempController = TextEditingController(text: "0.00");
  final TextEditingController _altController = TextEditingController(text: "0");
  final CarouselController _carouselController = CarouselController();
  final _pdfProvider = PDFProvider();

  bool _isLoading = true;
  bool _selPais = true;
  bool _finalizado = false;

  double _valArea = 0.0;
  double _valAltura = 0.0;
  double _valVolumen = 0.0;
  double _valDistMax = 0.0;
  double _alturaCiudad = 0.0;
  double _tempCiudad = 0.0;
  double _densidad = 0.0;
  double _caudalExtraccion = 0.0;
  double _renovaciones = 0.0;
  double _valVelInducida = 0.0;
  double _superficieVentilada = 0.0;
  double _cantEquipos = 0.0;

  String _ubicacion = "";
  String _pais = "";
  String _code = "";
  String _unidadArea = "m²";
  String _unidadAltura = "m";
  String _unidadVolumen = "m³";
  String _equipo = "JET-FAN (recomendado)";
  String _modelo = "";
  String _estado = "";
  String _ciudad = "";
  String _continenteAct = "AMN";
  String _paisConf = "";

  int _normativa = 0;
  int _intEquipos = 0;
  int _valNiveles = 1;
  int _nivelActual = 1;

  Map<String, String> _paisesDrop = {};
  Map<int, Map<String, dynamic>> _confNiveles = {};

  List<String> _paisesKeys = [];

  final Map<String, Map<String, Map<String, double>>> _tempAltCiudad = {};
  final Map<String, String> _continentes = {
    "EUR" : "Europa",
    "ASI" : "Asia",
    "AFR" : "Africa",
    "OCE" : "Oceanía",
    "AMN" : "América del norte",
    "AMS" : "América del sur",
    "AMC" : "América central"
  };
  final Map<String, Map<String, String>> _paisContinente = {};
  final Map<String, Map<String, String>> _estados = {};
  final Map<String, Map<String, List<String>>> _ciudades = {};
  final Map<String, Map<String, double>> _listaEquipos = {
    "JET-FAN (recomendado)" : {},
    "TUBULARES" : {
      "RBC-400" : 11.53,
      "RBC-500" : 30.11,
      "RBC-630" : 70.64,
      "RBC-800" : 80.92,
      "RBW-400" : 11.53,
      "RBW-500" : 30.11,
      "RBW-630" : 70.64,
      "RBW-800" : 80.92,
      "TAT-1000/H" : 339.16,
      "TAT-1000/L" : 149.92,
      "TAT-630/H" : 82.45,
      "TAT-630/L" : 43.71,
      "TAT-800/H" : 171.87,
      "TAT-800/L" : 74.93,
      "TTB-250" : 6.69,
      "TTB-315" : 8.54,
      "TTB-400" : 11.00,
      "TTB-500" : 35.89,
      "TTT-400" : 11.00,
      "TTT-500" : 35.89,
    }
  };
  final Map<String, Map<String, String>> _listaEquiposImagen = {};

  static const List<String> _unidadesArea = ["m²", "ft²"];
  static const List<String> _unidadesAltura = ["m", "ft"];
  static const List<String> _unidadesVolumen = ["m³", "ft³"];
  static const List<String> _equipos = ["JET-FAN (recomendado)", "TUBULARES"];
  static const Map<int, String> _normativas = {
    1: "ASHRAE 62.1-2010",
    2: "NFPA 88-A",
    3: "Reglamento de construcción CDMX",
  };

  @override
  void initState() {
    super.initState();
    _confNiveles[1] = {};
    _confNiveles[1] = {
      "area": 0.0,
      "unidadArea": "m²",
      "altura": 0.0,
      "unidadAltura": "m",
      "volumen": 0.0,
      "unidadVolumen": "m³",
      "normativa": "",
      "caudal": 0.0,
      "renovaciones": 0.0,
      "distanciaMax": 0.0,
      "velInd": 0.0,
      "velRec": "0.25",
      "equipo": "JET-FAN (recomendado)",
      "modelo": "",
      "empuje": 0.0,
      "V2": 0.0,
      "supVent": 0.0,
      "equipos": 0.0,
      "equiposTot": 0,
      "equipoIMG": "",
    };

    _initVariables(_confNiveles[1]!);

    _pais = widget.pais;
    _code = widget.code;

    _leerDatos();
  }

  Future<void> _leerDatos() async{
    await _readJson();

    if(widget.datos.isEmpty){
      setState(() => _isLoading = false);
    }else{
      final datosDec = utf8.decode(base64.decode(widget.datos));
      final datosArr = jsonDecode(datosDec);
      final ubicacion = datosArr["ubicacion"];

      //configuración de la ubicación
      if(ubicacion.keys.contains("region")) _continenteAct = ubicacion["region"];
      if(ubicacion.keys.contains("pais")) _paisConf = ubicacion["pais"];
      if(ubicacion.keys.contains("estado")) _estado = ubicacion["estado"];
      if(ubicacion.keys.contains("ciudad")) _ciudad = ubicacion["ciudad"];
      if(ubicacion.keys.contains("ubiStr")) _ubicacion = ubicacion["ubiStr"];

      _paisesDrop = _paisContinente[_continenteAct]!;
      _paisesKeys = _paisesDrop.keys.toList();

      if(datosArr.keys.contains("datos")){
        if(datosArr["datos"]["temperatura"] == "0"){
          setState(() => _isLoading = false);
          return;
        }else{
          _tempCiudad = double.parse(datosArr["datos"]["temperatura"]);
        }

        if(datosArr["datos"]["altura"] == "0"){
          setState(() => _isLoading = false);
          return;
        }else{
          _alturaCiudad = double.parse(datosArr["datos"]["altura"]);
        }

        if(_paisConf != "MX"){
          _altController.text = "$_alturaCiudad";
          _tempController.text = "$_tempCiudad";
        }

        _densidad = double.parse(datosArr["datos"]["densidad"]);
        _valNiveles = int.parse(datosArr["datos"]["cantNiveles"]);
        _nivelesController.text = datosArr["datos"]["cantNiveles"];

        final niveles = datosArr["niveles"];
        niveles.forEach((k, v){
          final dec = utf8.decode(base64Decode(v));
          final arr = jsonDecode(dec);
          final key = int.parse(k);
          if(_confNiveles[key] == null){
            _confNiveles[key] = {};
          }

          arr.forEach((k0, v0){
            _confNiveles[key]![k0] = v0;
          });
        });

        _initVariables(_confNiveles[1]!);
        _finalizado = _finalizar();
      }

      setState(() => _isLoading = false);
    }
  }

  Future<void> _readJson() async{
    String pais = widget.pais.split(" ")[1];
    pais = pais.replaceAll("(", "").replaceAll(")", "");

    final String paisesEstados = await rootBundle.loadString('assets/paises_db_simple.json');
    final String municipios = await rootBundle.loadString('assets/paises_db.json');
    final String ciudadesMX = await rootBundle.loadString('temperaturas_MX.json');
    final String jetfan = await rootBundle.loadString('empujes.json');

    final paisesEstadosArr = await jsonDecode(paisesEstados);
    final ciudadesArr = await jsonDecode(ciudadesMX);
    final jetfanArr = await jsonDecode(jetfan);

    jetfanArr.forEach((k, v){
      if(_listaEquiposImagen["JET-FAN (recomendado)"] == null) _listaEquiposImagen["JET-FAN (recomendado)"] = {};

      _listaEquipos["JET-FAN (recomendado)"]![k] = v["empuje"];
      _listaEquiposImagen["JET-FAN (recomendado)"]![k] = v["tipo"];
    });

    final estados = paisesEstadosArr['estados'];
    final paises = paisesEstadosArr['paises'];

    paises.forEach((pais){
      final continent = pais['ContinentCode'];
      final tmp = _paisContinente[continent];
      final code = pais['CountryCode'];

      String flag = code.toUpperCase();
      flag = flag.replaceAllMapped(RegExp(r'[A-Z]'), (match) => String.fromCharCode(match.group(0)!.codeUnitAt(0) + 127397));

      final paisStr = "$flag - ${pais['CountryName']} (${pais['CountryCode']})";

      if(tmp != null){
        _paisContinente[continent]![code] = paisStr;
      }else{
        _paisContinente[continent] = {};
        _paisContinente[continent]![code] = paisStr;
      }
    });

    _paisesDrop = _paisContinente[_continenteAct]!;
    _paisContinente[_continenteAct]!.keys.forEach((element) {
      if(element != "MX") _paisesKeys.add(element);
    });

    _paisesKeys.insert(0, "MX");
    estados.forEach((estado){
      final paisCode = estado['SUCountry'];
      final tmp = _estados[paisCode];
      final estadoStr = "${estado['SUName']} (${estado['SUCode']})";

      if(tmp == null){
        _estados[paisCode] = {};
        _estados[paisCode]![estado['SUCode']] = estadoStr;
      }else{
        _estados[paisCode]![estado['SUCode']] = estadoStr;
      }
    });

    final munIntDec = await jsonDecode(municipios);
    munIntDec[0]["data"].forEach((item){
      final paisCode = item['Country'];
      final estadoCode = item['Subdivision'];
      final name = item['Name'];

      if(estadoCode != null){
        if(_ciudades[paisCode] == null){
          _ciudades[paisCode] = {};
        }

        if(_ciudades[paisCode]![estadoCode] == null){
          _ciudades[paisCode]![estadoCode] = [];
        }

        if(paisCode != "MX") _ciudades[paisCode]![estadoCode]!.add(name);
      }
    });

    ciudadesArr["MX"].forEach((k, v){
      if(_tempAltCiudad[k] == null){
        _tempAltCiudad[k] = {};
      }

      v.forEach((k0, v0){
        _ciudades["MX"]![k]!.add(k0);
        if(_tempAltCiudad[k]![k0] == null){
          _tempAltCiudad[k]![k0] = {};
        }

        v0.forEach((k1, v1){
          if(_tempAltCiudad[k]![k0]![k1] == null){
            _tempAltCiudad[k]![k0]![k1] = v1;
          }
        });
      });
    });
  }

  Future<bool> _cambiarDatos(String datos, String archPDF, String status) async{
    final url = Uri.https("smart.solerpalau.mx", "PR/api/v1/quiosco/matrizMemoriasCalculo/actualizarProyecto");
    final res = await http.post(url,
      headers: {
        "Authorization": "Bearer ${widget.token}"
      },
      body: {
        "IDUSUARIO": widget.idUsuario,
        "IDPROYECTO": widget.idProyecto,
        "FMODIF": DateTime.now().toIso8601String().substring(0, 19),
        "ESTATUS": status,
        "DATOS": base64Encode(utf8.encode(datos)),
        "ARCHPDF" : archPDF
      },
    );

    final decoded = jsonDecode(res.body);
    return decoded['response'];
  }

  void _initVariables(Map<String, dynamic> datos){
    _valArea = datos["area"].runtimeType == String ? double.parse(datos["area"]) : datos["area"];
    _areaController.text = "$_valArea";
    _unidadArea = datos["unidadArea"];

    _valAltura = datos["altura"].runtimeType == String ? double.parse(datos["altura"]) : datos["altura"];
    _alturaController.text = "$_valAltura";
    _unidadAltura = datos["unidadAltura"];

    _valVolumen = datos["volumen"].runtimeType == String ? double.parse(datos["volumen"]) : datos["volumen"];
    _unidadVolumen = datos["unidadVolumen"];

    int normativa = 0;
    _normativas.forEach((key, value) {
      if(value == datos["normativa"]){
        normativa = key;
      }
    });

    _normativa = normativa;
    _caudalExtraccion = datos["caudal"].runtimeType == String ? double.parse(datos["caudal"]) : datos["caudal"];
    _renovaciones = datos["renovaciones"].runtimeType == String ? double.parse(datos["renovaciones"]) : datos["renovaciones"];

    _valDistMax = datos["distanciaMax"].runtimeType == String ? double.parse(datos["distanciaMax"]) : datos["distanciaMax"];
    _distMaxController.text = "$_valDistMax";

    _valVelInducida = datos["velInd"].runtimeType == String ? double.parse(datos["velInd"]) : datos["velInd"];
    _equipo = datos["equipo"];
    _modelo = datos["modelo"];

    _superficieVentilada = datos["supVent"].runtimeType == String ? double.parse(datos["supVent"]) : datos["supVent"];
    _cantEquipos = datos["equipos"].runtimeType == String ? double.parse(datos["equipos"]) : datos["equipos"];
    _intEquipos = datos["equiposTot"].runtimeType == String ? int.parse(datos["equiposTot"]) : datos["equiposTot"];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: _isLoading ? const Center(
        child: CircularProgressIndicator(),
      ) : _selPais ? AlertDialog(
        title: Text(
          "Configuración",
          style: GoogleFonts.roboto(),
        ),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            SizedBox(
              width: double.infinity,
              child: Text(
                "Selecciona el país donde se ubicará el proyecto:",
                textAlign: TextAlign.left,
                style: GoogleFonts.roboto(),
              ),
            ),
            const SizedBox(
              height: 8.0,
            ),
            DropdownButton<String>(
              items: _continentes.keys.toList().map((e) => DropdownMenuItem<String>(
                child: Text(
                  _continentes[e]!,
                  style: GoogleFonts.roboto(),
                ),
                value: e,
              )).toList(),
              value: _continenteAct,
              isExpanded: true,
              onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
              onChanged: (val) => setState((){
                _paisConf = "";
                _estado = "";
                _ciudad = "";
                _tempCiudad = 0;
                _alturaCiudad = 0;
                _continenteAct = val!;

                _paisesDrop = _paisContinente[_continenteAct]!;
                _paisesKeys = [];
                _paisContinente[_continenteAct]!.keys.forEach((element) {
                  if(element != "MX") _paisesKeys.add(element);
                });

                if(_continenteAct == "AMN") _paisesKeys.insert(0, "MX");
              }),
            ),
            const SizedBox(
              height: 8.0,
            ),
            DropdownButton<String>(
              value: _paisConf.isEmpty ? null : _paisConf,
              hint: Text(
                "Selecciona una opción",
                style: GoogleFonts.roboto(
                  color: Colors.grey,
                  fontStyle: FontStyle.italic,
                ),
              ),
              onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
              onChanged: (nuevoPais) => setState((){
                _estado = "";
                _ciudad = "";
                _tempCiudad = 0;
                _alturaCiudad = 0;
                _paisConf = nuevoPais!;
              }),
              items: _paisesKeys.map((e) => DropdownMenuItem<String>(
                child: Text(
                  _paisesDrop[e]!,
                  style: GoogleFonts.roboto(),
                ),
                value: e,
              )).toList(),
              isExpanded: true,
            )
          ],
        ),
        actions: [
          TextButton(
            child: const Text("Regresar"),
            onPressed: () => Navigator.pop(context),
          ),
          TextButton(
            child: const Text("Aceptar"),
            onPressed: () async{
              if(_paisConf.isEmpty){
                Fluttertoast.showToast(
                  msg: "Por favor selecciona un país.",
                  toastLength: Toast.LENGTH_SHORT,
                  timeInSecForIosWeb: 4,
                  gravity: ToastGravity.CENTER,
                  webBgColor: "linear-gradient(to right, #b40404, #ff0000)",
                );
              }else{
                final Map<String, String> niveles = {};
                _confNiveles.forEach((key, value) {
                  final Map<String, String> nivel = {};
                  value.forEach((key0, value0) {
                    if(value0.runtimeType == String){
                      nivel[key0] = value0;
                    }else{
                      nivel[key0] = "$value0";
                    }
                  });

                  final nivelStr = base64.encode(utf8.encode(jsonEncode(nivel)));
                  niveles["$key"] = nivelStr;
                });

                setState((){
                  _isLoading = true;
                  _selPais = false;
                });
                Map<String, Map<String, String>> info = {
                  "ubicacion": {
                    "region": _continenteAct,
                    "pais": _paisConf,
                    "estado": _estado,
                    "ciudad": _ciudad,
                    "ubiStr": _ubicacion,
                  },
                  "datos": {
                    "temperatura": "$_tempCiudad",
                    "altura": "$_alturaCiudad",
                    "cantNiveles": "$_valNiveles",
                    "densidad": "$_densidad",
                  },
                  "niveles": niveles,
                };

                final infoStr = jsonEncode(info);
                _finalizado = _finalizar();
                final guardado = await _cambiarDatos(infoStr, "", _finalizado ? "F" : "C");
                if(!guardado){
                  Navigator.pop(context);
                  Fluttertoast.showToast(
                    msg: "Hubo un error al intentar guardar el proyecto, intentelo de nuevo más tarde.",
                    toastLength: Toast.LENGTH_SHORT,
                    timeInSecForIosWeb: 4,
                    gravity: ToastGravity.CENTER,
                    webBgColor: "linear-gradient(to right, #b40404, #ff0000)",
                  );
                }

                setState(() => _isLoading = false);
              }
            },
          )
        ],
      ) : LayoutBuilder(
        builder: (context, constraints){
          final parentWidth = constraints.maxWidth;
          double containerWidth = parentWidth > 1440
              ? parentWidth*0.5 : parentWidth > 1280 && parentWidth <= 1440
              ? parentWidth*0.6 : parentWidth > 1080 && parentWidth <= 1280
              ? parentWidth*0.75 : parentWidth > 900 && parentWidth <= 1080
              ? parentWidth*0.8 : parentWidth > 720 && parentWidth <= 900
              ? parentWidth*0.85 : parentWidth > 540 && parentWidth <= 720
              ? parentWidth*0.9 : parentWidth;
          double containerMargin = (parentWidth - containerWidth) / 2;

          return Container(
            width: containerWidth,
            margin: EdgeInsets.symmetric(
              horizontal: containerMargin,
            ),
            child: Column(
              children: [
                const SizedBox(height: 8.0),
                Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 32.0,
                  ),
                  child: Row(
                    children: [
                      TextButton(
                        child: Text(
                          "Memoria de cálculo de ventilación de estacionamientos >",
                          style: GoogleFonts.roboto(
                            fontSize: 16.0,
                            fontWeight: FontWeight.bold,
                            fontStyle: FontStyle.italic,
                          ),
                        ),
                        onPressed: () async{
                          final accion = await showDialog(
                            context: context,
                            barrierDismissible: false,
                            builder: (context) => AlertDialog(
                              title: Text(
                                "Salir sin guardar",
                                textAlign: TextAlign.center,
                                style: GoogleFonts.roboto(
                                  fontWeight: FontWeight.bold,
                                  fontSize: 20.0,
                                  color: Colors.black87,
                                ),
                              ),
                              content: Text(
                                "¿Está seguro de salir sin guardar los cambios?",
                                textAlign: TextAlign.center,
                                style: GoogleFonts.roboto(
                                  fontSize: 16.0,
                                ),
                              ),
                              actions: [
                                TextButton(
                                  child: const Text("Salir sin guardar"),
                                  onPressed: () => Navigator.pop(context, "salir"),
                                ),
                                TextButton(
                                  child: const Text("Guardar y salir"),
                                  onPressed: () => Navigator.pop(context, "guardar"),
                                ),
                                TextButton(
                                  child: const Text("Cancelar"),
                                  onPressed: () => Navigator.pop(context, "cancelar"),
                                )
                              ],
                            ),
                          );

                          if(accion == "salir"){
                            Navigator.pop(context);
                          }else if(accion == "guardar"){
                            final Map<String, String> niveles = {};
                            _confNiveles.forEach((key, value) {
                              final Map<String, String> nivel = {};
                              value.forEach((key0, value0) {
                                if(value0.runtimeType == String){
                                  nivel[key0] = value0;
                                }else{
                                  nivel[key0] = "$value0";
                                }
                              });

                              final nivelStr = base64.encode(utf8.encode(jsonEncode(nivel)));
                              niveles["$key"] = nivelStr;
                            });

                            Map<String, Map<String, String>> info = {
                              "ubicacion": {
                                "region": _continenteAct,
                                "pais": _paisConf,
                                "estado": _estado,
                                "ciudad": _ciudad,
                                "ubiStr": _ubicacion,
                              },
                              "datos": {
                                "temperatura": "$_tempCiudad",
                                "altura": "$_alturaCiudad",
                                "cantNiveles": "$_valNiveles",
                                "densidad": "$_densidad",
                              },
                              "niveles": niveles,
                            };

                            final infoStr = jsonEncode(info);
                            final guardado = await _cambiarDatos(infoStr, "", _finalizado ? "F" : "C");
                            if(guardado){
                              Navigator.pop(context);
                            }else{
                              Fluttertoast.showToast(
                                msg: "Hubo un error al intentar guardar el proyecto, intentelo de nuevo más tarde.",
                                toastLength: Toast.LENGTH_SHORT,
                                timeInSecForIosWeb: 4,
                                gravity: ToastGravity.CENTER,
                                webBgColor: "linear-gradient(to right, #b40404, #ff0000)",
                              );
                            }
                          }
                        },
                        style: TextButton.styleFrom(
                          padding: const EdgeInsets.fromLTRB(0, 0, 8.0, 0),
                          minimumSize: const Size(0, 0),
                          tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                        ),
                      ),
                      const SizedBox(width: 8.0),
                      Expanded(
                        child: Container(
                          padding: const EdgeInsets.fromLTRB(0, 0, 8.0, 0),
                          child: Text(
                            "Extracción en estacionamientos cerrados",
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: GoogleFonts.roboto(
                              fontSize: 16.0,
                              color: Colors.black54,
                              fontWeight: FontWeight.bold,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                        ),
                      )
                    ],
                  ),
                ),
                const SizedBox(height: 8.0),
                EncabezadoPais(paisCode: _code, paisName: _pais),
                const SizedBox(height: 32.0),
                Image.asset(
                  "estacionamientos.png",
                  width: 120.0,
                ),
                const SizedBox(height: 48.0),
                Container(
                  width: double.infinity,
                  padding: const EdgeInsets.symmetric(
                    horizontal: 32.0,
                  ),
                  child: Text(
                    "Extracción en estacionamientos cerrados".toUpperCase(),
                    textAlign: TextAlign.center,
                    style: const TextStyle(
                      fontFamily: "Helvetica Neue Black Cond",
                      fontSize: 28.0,
                    ),
                  ),
                ),
                const SizedBox(height: 8.0),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 32.0),
                  width: double.infinity,
                  child: const Text(
                    "Por favor ingresa los datos requeridos para el cálculo del estacionamiento.",
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      fontFamily: "Helvetica Neue Light",
                      fontSize: 22.0,
                      fontWeight: FontWeight.w600,
                      color: Color.fromRGBO(104, 104, 104, 1),
                    ),
                  ),
                ),
                const SizedBox(height: 32.0),
                Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 32.0,
                  ),
                  child: Row(
                    children: [
                      RichText(
                        text: TextSpan(
                          style: GoogleFonts.roboto(fontSize: 18.0),
                          children: [
                            TextSpan(
                              text: "Ubicación: ",
                              style: GoogleFonts.roboto(fontWeight: FontWeight.bold),
                            ),
                            TextSpan(text: _paisContinente[_continenteAct]![_paisConf]),
                          ],
                        ),
                      ),
                      const SizedBox(width: 8.0),
                      Expanded(
                        child: DropdownButton<String>(
                          value: _estado.isEmpty ? null :  _estado,
                          hint: Text(
                            "Selecciona un estado",
                            style: GoogleFonts.roboto(
                              color: Colors.grey,
                              fontSize: 18.0,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                          focusColor: Colors.transparent,
                          items: _estados[_paisConf]!.keys.map((e) => DropdownMenuItem<String>(
                            value: e,
                            child: Text(
                              _estados[_paisConf]![e]!,
                              style: GoogleFonts.roboto(
                                fontSize: 18.0,
                              ),
                            ),
                          )).toList(),
                          onChanged: (value) => setState(()  {
                            _ciudad = "";
                            _estado = value!;
                          }),
                          isExpanded: true,
                        ),
                      ),
                      const SizedBox(width: 8.0),
                      Expanded(
                        child: DropdownButton<String>(
                          value: _ciudad.isEmpty ? null : _ciudad,
                          hint: Text(
                            "Selecciona un una ciudad",
                            style: GoogleFonts.roboto(
                              color: Colors.grey,
                              fontSize: 18.0,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                          disabledHint: Text(
                            "Aún no se ha seleccionado un estado",
                            style: GoogleFonts.roboto(
                              color: Colors.grey,
                              fontSize: 18.0,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                          focusColor: Colors.transparent,
                          items: _estado.isEmpty ? null : _ciudades[_paisConf]![_estado]!.map((e) => DropdownMenuItem<String>(
                            value: e,
                            child: Text(
                              e,
                              style: GoogleFonts.roboto(
                                fontSize: 18.0,
                              ),
                            ),
                          )).toList(),
                          onChanged: (val) => setState(() {
                            _ciudad = val!;

                            final paisStr = _paisesDrop[_paisConf];
                            final paisArr = paisStr!.split("-");
                            _ubicacion = "${paisArr.last.trim()}, ${_estados[_paisConf]![_estado]}, $_ciudad";

                            if(_paisConf == 'MX'){
                              _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                              _tempCiudad = _tempAltCiudad[_estado]![_ciudad]!["T"]!;
                              _alturaCiudad = _tempAltCiudad[_estado]![_ciudad]!["H"]!;
                            }
                          }),
                          isExpanded: true,
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 16.0),
                if(_paisConf =='MX')
                  AnimatedCrossFade(
                    firstChild: Container(),
                    secondChild: Container(
                      margin: const EdgeInsets.symmetric(
                        horizontal: 32.0,
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Expanded(
                            child: RichText(
                              textAlign: TextAlign.center,
                              text: TextSpan(
                                style: GoogleFonts.roboto(fontSize: 18.0),
                                children: [
                                  TextSpan(
                                    text: "Temperatura: ",
                                    style: GoogleFonts.roboto(fontWeight: FontWeight.bold),
                                  ),
                                  TextSpan(text: "$_tempCiudad °C"),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 8.0),
                          Expanded(
                            child: RichText(
                              textAlign: TextAlign.center,
                              text: TextSpan(
                                style: GoogleFonts.roboto(fontSize: 18.0),
                                children: [
                                  TextSpan(
                                    text: "Altura: ",
                                    style: GoogleFonts.roboto(fontWeight: FontWeight.bold),
                                  ),
                                  TextSpan(text: "$_alturaCiudad m.s.n.m"),
                                ],
                              ),
                            ),
                          ),
                          const SizedBox(width: 8.0),
                          Expanded(
                            child: RichText(
                              textAlign: TextAlign.center,
                              text: TextSpan(
                                style: GoogleFonts.roboto(fontSize: 18.0),
                                children: [
                                  TextSpan(
                                    text: "Densidad: ",
                                    style: GoogleFonts.roboto(fontWeight: FontWeight.bold),
                                  ),
                                  TextSpan(text: _densidad.toStringAsFixed(2)),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    duration: const Duration(milliseconds: 250),
                    crossFadeState: _ciudad.isEmpty ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                  ),
                if(_paisConf !='MX')
                  AnimatedCrossFade(
                    firstChild: Container(),
                    secondChild: Container(
                      margin: const EdgeInsets.symmetric(
                        horizontal: 32.0,
                      ),
                      child: Row(
                        children: [
                          Expanded(
                            child: Row(
                              children: [
                                Text(
                                  "Temperatura:",
                                  textAlign: TextAlign.center,
                                  style: GoogleFonts.roboto(
                                    fontSize: 18.0,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                                const SizedBox(width: 8.0),
                                Expanded(
                                  child: SizedBox(
                                    height: 64.0,
                                    width: double.infinity,
                                    child: Stack(
                                      alignment: Alignment.center,
                                      children: [
                                        TextField(
                                          textAlign: TextAlign.center,
                                          controller: _tempController,
                                          maxLength: 5,
                                          decoration: const InputDecoration(
                                            counterText: "",
                                            counterStyle: TextStyle(
                                              height: double.minPositive,
                                            ),
                                          ),
                                          inputFormatters: [
                                            DecimalTextInputFormatter()
                                          ],
                                          onChanged: (val) => setState(() {
                                            if(val.isEmpty){
                                              _tempCiudad = 0;
                                            }else{
                                              _tempCiudad = double.parse(val);
                                            }

                                            _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                          }),
                                        ),
                                        Positioned(
                                          left: 0.0,
                                          child: IconButton(
                                            icon: const Icon(
                                              Icons.remove,
                                              color: Colors.black45,
                                            ),
                                            onPressed: () => setState(() {
                                              _tempCiudad = _tempCiudad - 0.1;
                                              if(_tempCiudad < 0){
                                                _tempCiudad = 0;
                                              }

                                              _tempController.text = _tempCiudad.toStringAsFixed(2);
                                              _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                            }),
                                          ),
                                        ),
                                        Positioned(
                                          right: 0.0,
                                          child: IconButton(
                                            icon: const Icon(
                                              Icons.add,
                                              color: Colors.black45,
                                            ),
                                            onPressed: () => setState(() {
                                              _tempCiudad = _tempCiudad + 0.1;
                                              if(_tempCiudad > 99){
                                                _tempCiudad = 99;
                                              }

                                              _tempController.text = _tempCiudad.toStringAsFixed(2);
                                              _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                            }),
                                          ),
                                        )
                                      ],
                                    ),
                                  ),
                                ),
                                const SizedBox(width: 8.0),
                                Text(
                                  "°C",
                                  textAlign: TextAlign.center,
                                  style: GoogleFonts.roboto(
                                    fontSize: 18.0,
                                  ),
                                ),
                              ],
                            ),
                          ),
                          const SizedBox(width: 8.0),
                          Expanded(
                            child: Row(
                              children: [
                                Text(
                                  "Altura:",
                                  textAlign: TextAlign.center,
                                  style: GoogleFonts.roboto(
                                    fontSize: 18.0,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                                const SizedBox(width: 8.0),
                                Expanded(
                                  child: SizedBox(
                                    height: 64.0,
                                    width: double.infinity,
                                    child: Stack(
                                      alignment: Alignment.center,
                                      children: [
                                        TextField(
                                          textAlign: TextAlign.center,
                                          controller: _altController,
                                          maxLength: 10,
                                          decoration: const InputDecoration(
                                            counterText: "",
                                            counterStyle: TextStyle(
                                              height: double.minPositive,
                                            ),
                                          ),
                                          inputFormatters: [
                                            DecimalTextInputFormatter()
                                          ],
                                          onChanged: (val) => setState(() {
                                            if(val.isEmpty){
                                              _alturaCiudad = 0;
                                            }else{
                                              _alturaCiudad = double.parse(val);
                                            }

                                            _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                          }),
                                        ),
                                        Positioned(
                                          left: 0.0,
                                          child: IconButton(
                                            icon: const Icon(
                                              Icons.remove,
                                              color: Colors.black45,
                                            ),
                                            onPressed: () => setState(() {
                                              _alturaCiudad = _alturaCiudad - 0.1;
                                              if(_alturaCiudad < 0){
                                                _alturaCiudad = 0;
                                              }

                                              _altController.text = _alturaCiudad.toStringAsFixed(2);
                                              _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                            }),
                                          ),
                                        ),
                                        Positioned(
                                          right: 0.0,
                                          child: IconButton(
                                            icon: const Icon(
                                              Icons.add,
                                              color: Colors.black45,
                                            ),
                                            onPressed: () => setState(() {
                                              _alturaCiudad = _alturaCiudad + 0.1;
                                              if(_alturaCiudad > 9999){
                                                _alturaCiudad = 9999;
                                              }

                                              _altController.text = _alturaCiudad.toStringAsFixed(2);
                                              _densidad = (1 / ((0.9318 + (0.00341 * _tempCiudad)) * math.exp(0.0001186 * _alturaCiudad))) * 1.2;
                                            }),
                                          ),
                                        )
                                      ],
                                    ),
                                  ),
                                ),
                                const SizedBox(width: 8.0),
                                Text(
                                  "m.s.n.m",
                                  textAlign: TextAlign.center,
                                  style: GoogleFonts.roboto(
                                    fontSize: 18.0,
                                  ),
                                ),
                              ],
                            ),
                          ),
                          const SizedBox(width: 8.0),
                          Expanded(
                            child: RichText(
                              textAlign: TextAlign.center,
                              text: TextSpan(
                                style: GoogleFonts.roboto(fontSize: 18.0),
                                children: [
                                  TextSpan(
                                    text: "Densidad: ",
                                    style: GoogleFonts.roboto(fontWeight: FontWeight.bold),
                                  ),
                                  TextSpan(text: _densidad.toStringAsFixed(2)),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    duration: const Duration(milliseconds: 250),
                    crossFadeState: _ciudad.isEmpty ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                  ),
                const SizedBox(height: 16.0),
                Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 32.0,
                  ),
                  child: Row(
                    children: [
                      Text(
                        "Cantidad de Niveles:",
                        style: GoogleFonts.roboto(
                          fontWeight: FontWeight.bold,
                          fontSize: 18.0,
                        ),
                      ),
                      const SizedBox(width: 8.0),
                      Expanded(
                        child: SizedBox(
                          height: 64.0,
                          width: double.infinity,
                          child: Stack(
                            alignment: Alignment.center,
                            children: [
                              TextField(
                                textAlign: TextAlign.center,
                                controller: _nivelesController,
                                maxLength: 2,
                                decoration: const InputDecoration(
                                  counterText: "",
                                  counterStyle: TextStyle(
                                    height: double.minPositive,
                                  ),
                                ),
                                inputFormatters: [
                                  DecimalTextInputFormatter()
                                ],
                                onChanged: (val) => setState(() {
                                  if(val.isEmpty){
                                    _valNiveles = 1;
                                  }else if(val == "0"){
                                    _nivelesController.text = "1";
                                    _valNiveles = 1;
                                  }else{
                                    _valNiveles = int.parse(val);
                                  }

                                  _valNiveles = _valNiveles;

                                  Map<int, Map<String, dynamic>> nivelesTmp = {};
                                  for(int i = 1; i <= _valNiveles; i++){
                                    if(_confNiveles[i] == null){
                                      nivelesTmp[i] = {
                                        "area": 0.0,
                                        "unidadArea": "m²",
                                        "altura": 0.0,
                                        "unidadAltura": "m",
                                        "volumen": 0.0,
                                        "unidadVolumen": "m³",
                                        "normativa": "",
                                        "caudal": 0.0,
                                        "renovaciones": 0.0,
                                        "distanciaMax": 0.0,
                                        "velInd": 0.0,
                                        "velRec": "0.25",
                                        "equipo": "JET-FAN (recomendado)",
                                        "modelo": "",
                                        "empuje": 0.0,
                                        "V2": 0.0,
                                        "supVent": 0.0,
                                        "equipos": 0.0,
                                        "equiposTot": 0
                                      };
                                    }else{
                                      nivelesTmp[i] = _confNiveles[i]!;
                                    }
                                  }

                                  _confNiveles = nivelesTmp;
                                  _carouselController.jumpToPage(0);
                                  _finalizado = _finalizar();
                                }),
                              ),
                              Positioned(
                                left: 0.0,
                                child: IconButton(
                                  icon: const Icon(
                                    Icons.remove,
                                    color: Colors.black45,
                                  ),
                                  onPressed: _valNiveles > 1 ? () => setState(() {
                                    _valNiveles = _valNiveles - 1;
                                    if(_valNiveles < 1){
                                      _valNiveles = 1;
                                    }

                                    _nivelesController.text = "$_valNiveles";

                                    Map<int, Map<String, dynamic>> nivelesTmp = {};
                                    for(int i = 1; i <= _valNiveles; i++){
                                      if(_confNiveles[i] == null){
                                        nivelesTmp[i] = {
                                          "area": 0.0,
                                          "unidadArea": "m²",
                                          "altura": 0.0,
                                          "unidadAltura": "m",
                                          "volumen": 0.0,
                                          "unidadVolumen": "m³",
                                          "normativa": "",
                                          "caudal": 0.0,
                                          "renovaciones": 0.0,
                                          "distanciaMax": 0.0,
                                          "velInd": 0.0,
                                          "velRec": "0.25",
                                          "equipo": "JET-FAN (recomendado)",
                                          "modelo": "",
                                          "empuje": 0.0,
                                          "V2": 0.0,
                                          "supVent": 0.0,
                                          "equipos": 0.0,
                                          "equiposTot": 0
                                        };
                                      }else{
                                        nivelesTmp[i] = _confNiveles[i]!;
                                      }
                                    }

                                    _confNiveles = nivelesTmp;
                                    _carouselController.jumpToPage(0);
                                    _finalizado = _finalizar();
                                  }) : null,
                                ),
                              ),
                              Positioned(
                                right: 0.0,
                                child: IconButton(
                                  icon: const Icon(
                                    Icons.add,
                                    color: Colors.black45,
                                  ),
                                  onPressed: _valNiveles < 99 ? () => setState(() {
                                    _valNiveles = _valNiveles + 1;
                                    if(_valNiveles > 99){
                                      _valNiveles = 99;
                                    }

                                    _nivelesController.text = "$_valNiveles";

                                    Map<int, Map<String, dynamic>> nivelesTmp = {};
                                    for(int i = 1; i <= _valNiveles; i++){
                                      if(_confNiveles[i] == null){
                                        nivelesTmp[i] = {
                                          "area": 0.0,
                                          "unidadArea": "m²",
                                          "altura": 0.0,
                                          "unidadAltura": "m",
                                          "volumen": 0.0,
                                          "unidadVolumen": "m³",
                                          "normativa": "",
                                          "caudal": 0.0,
                                          "renovaciones": 0.0,
                                          "distanciaMax": 0.0,
                                          "velInd": 0.0,
                                          "velRec": "0.25",
                                          "equipo": "JET-FAN (recomendado)",
                                          "modelo": "",
                                          "empuje": 0.0,
                                          "V2": 0.0,
                                          "supVent": 0.0,
                                          "equipos": 0.0,
                                          "equiposTot": 0
                                        };
                                      }else{
                                        nivelesTmp[i] = _confNiveles[i]!;
                                      }
                                    }

                                    _confNiveles = nivelesTmp;
                                    _carouselController.jumpToPage(0);
                                    _finalizado = _finalizar();
                                  }) : null,
                                ),
                              )
                            ],
                          ),
                        ),
                      )
                    ],
                  ),
                ),
                const SizedBox(height: 8.0),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 32.0),
                  width: double.infinity,
                  child: Text(
                    "Configuración del nivel $_nivelActual.",
                    textAlign: TextAlign.center,
                    style: GoogleFonts.robotoSlab(
                      fontSize: 16.0,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                const SizedBox(height: 8.0),
                Expanded(
                  child: SizedBox(
                    width: double.infinity,
                    height: double.infinity,
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        CarouselSlider.builder(
                          itemCount: _valNiveles,
                          itemBuilder: (context, itemIndex, viewIndex) => SizedBox(
                            width: double.infinity,
                            height: double.infinity,
                            child: SingleChildScrollView(
                              child: Column(
                                children: [
                                  Container(
                                    margin: const EdgeInsets.symmetric(
                                      horizontal: 32.0,
                                    ),
                                    child: Row(
                                      children: [
                                        Text(
                                          "Área:",
                                          style: GoogleFonts.roboto(
                                            fontWeight: FontWeight.bold,
                                            fontSize: 18.0,
                                          ),
                                        ),
                                        const SizedBox(width: 8.0),
                                        Expanded(
                                          child: SizedBox(
                                            height: 64.0,
                                            width: double.infinity,
                                            child: Stack(
                                              alignment: Alignment.center,
                                              children: [
                                                TextField(
                                                  textAlign: TextAlign.center,
                                                  controller: _areaController,
                                                  maxLength: 10,
                                                  decoration: const InputDecoration(
                                                    counterText: "",
                                                    counterStyle: TextStyle(
                                                      height: double.minPositive,
                                                    ),
                                                  ),
                                                  inputFormatters: [
                                                    DecimalTextInputFormatter()
                                                  ],
                                                  onChanged: (val){
                                                    if(val.isEmpty){
                                                      _valArea = 0.0;
                                                    }else{
                                                      _valArea = double.parse(val);
                                                    }

                                                    _confNiveles[_nivelActual]!["area"] = _valArea;
                                                    _calcularVolumen();
                                                  },
                                                ),
                                                Positioned(
                                                  left: 0.0,
                                                  child: IconButton(
                                                    icon: const Icon(
                                                      Icons.remove,
                                                      color: Colors.black45,
                                                    ),
                                                    onPressed: () => setState(() {
                                                      _valArea = _valArea - 0.1;

                                                      if(_valArea < 0){
                                                        _valArea = 0.0;
                                                      }

                                                      _confNiveles[_nivelActual]!["area"] = _valArea;
                                                      _areaController.text = _valArea.toStringAsFixed(2);
                                                      _calcularVolumen();
                                                    }),
                                                  ),
                                                ),
                                                Positioned(
                                                  right: 0.0,
                                                  child: IconButton(
                                                    icon: const Icon(
                                                      Icons.add,
                                                      color: Colors.black45,
                                                    ),
                                                    onPressed: () => setState(() {
                                                      _valArea = _valArea + 0.1;
                                                      if(_valArea > 9999999){
                                                        _valArea = 9999999.9;
                                                      }

                                                      _confNiveles[_nivelActual]!["area"] = _valArea;
                                                      _areaController.text = _valArea.toStringAsFixed(2);
                                                      _calcularVolumen();
                                                    }),
                                                  ),
                                                )
                                              ],
                                            ),
                                          ),
                                        ),
                                        const SizedBox(width: 8.0),
                                        DropdownButton<String>(
                                          focusColor: Colors.transparent,
                                          value: _unidadArea,
                                          onChanged: (value) => setState(() {
                                            _unidadArea = value!;
                                            _confNiveles[_nivelActual]!["unidadArea"] = _unidadArea;
                                            _calcularVolumen();
                                          }),
                                          items: _unidadesArea.map((e) => DropdownMenuItem<String>(
                                            child: Text(
                                              e,
                                              style: GoogleFonts.roboto(
                                                fontSize: 18.0,
                                              ),
                                            ),
                                            value: e,
                                          )).toList(),
                                        ),
                                        const SizedBox(width: 8.0),
                                        IconButton(
                                          icon: const Icon(
                                            Icons.info_outline,
                                          ),
                                          onPressed: () =>  showDialog(
                                            context: context,
                                            barrierDismissible: true,
                                            builder: (context) => const AlertDialog(
                                              title: Text("Área"),
                                              content: Text("Es la superficie total a ventilar."),
                                            ),
                                          ),
                                        )
                                      ],
                                    ),
                                  ),
                                  const SizedBox(height: 16.0),
                                  Container(
                                    margin: const EdgeInsets.symmetric(
                                      horizontal: 32.0,
                                    ),
                                    child: Row(
                                      children: [
                                        Text(
                                          "Altura:",
                                          style: GoogleFonts.roboto(
                                            fontWeight: FontWeight.bold,
                                            fontSize: 18.0,
                                          ),
                                        ),
                                        const SizedBox(width: 8.0),
                                        Expanded(
                                          child: SizedBox(
                                            height: 64.0,
                                            width: double.infinity,
                                            child: Stack(
                                              alignment: Alignment.center,
                                              children: [
                                                TextField(
                                                  textAlign: TextAlign.center,
                                                  controller: _alturaController,
                                                  maxLength: 10,
                                                  decoration: const InputDecoration(
                                                    counterText: "",
                                                    counterStyle: TextStyle(
                                                      height: double.minPositive,
                                                    ),
                                                  ),
                                                  inputFormatters: [
                                                    DecimalTextInputFormatter()
                                                  ],
                                                  onChanged: (val){
                                                    if(val.isEmpty){
                                                      _valAltura = 0;
                                                    }else{
                                                      _valAltura = double.parse(val);
                                                    }

                                                    _confNiveles[_nivelActual]!["altura"] = _valAltura;
                                                    _calcularVolumen();
                                                  },
                                                ),
                                                Positioned(
                                                  left: 0.0,
                                                  child: IconButton(
                                                    icon: const Icon(
                                                      Icons.remove,
                                                      color: Colors.black45,
                                                    ),
                                                    onPressed: () => setState(() {
                                                      _valAltura = _valAltura - 0.1;

                                                      if(_valAltura < 0){
                                                        _valAltura = 0.0;
                                                      }

                                                      _confNiveles[_nivelActual]!["altura"] = _valAltura;
                                                      _alturaController.text = _valAltura.toStringAsFixed(2);
                                                      _calcularVolumen();
                                                    }),
                                                  ),
                                                ),
                                                Positioned(
                                                  right: 0.0,
                                                  child: IconButton(
                                                    icon: const Icon(
                                                      Icons.add,
                                                      color: Colors.black45,
                                                    ),
                                                    onPressed: () => setState(() {
                                                      _valAltura = _valAltura + 0.1;
                                                      if(_valAltura > 9999999){
                                                        _valAltura = 9999999.9;
                                                      }

                                                      _confNiveles[_nivelActual]!["altura"] = _valAltura;
                                                      _alturaController.text = _valAltura.toStringAsFixed(2);
                                                      _calcularVolumen();
                                                    }),
                                                  ),
                                                )
                                              ],
                                            ),
                                          ),
                                        ),
                                        const SizedBox(width: 8.0),
                                        DropdownButton<String>(
                                          focusColor: Colors.transparent,
                                          value: _unidadAltura,
                                          onChanged: (value) => setState(() {
                                            _unidadAltura = value!;
                                            _confNiveles[_nivelActual]!["unidadAltura"] = _unidadAltura;
                                            _calcularVolumen();
                                          }),
                                          items: _unidadesAltura.map((e) => DropdownMenuItem<String>(
                                            child: Text(
                                              e,
                                              style: GoogleFonts.roboto(
                                                fontSize: 18.0,
                                              ),
                                            ),
                                            value: e,
                                          )).toList(),
                                        ),
                                        const SizedBox(width: 8.0),
                                        IconButton(
                                          icon: const Icon(
                                            Icons.info_outline,
                                          ),
                                          onPressed: () =>  showDialog(
                                            context: context,
                                            barrierDismissible: true,
                                            builder: (context) => const AlertDialog(
                                              title: Text("Altura"),
                                              content: Text("Es la altura libre neta."),
                                            ),
                                          ),
                                        )
                                      ],
                                    ),
                                  ),
                                  AnimatedCrossFade(
                                    firstChild: Container(),
                                    secondChild: Column(
                                      children: [
                                        const SizedBox(height: 16.0),
                                        Row(
                                          mainAxisAlignment: MainAxisAlignment.center,
                                          crossAxisAlignment: CrossAxisAlignment.center,
                                          children: [
                                            RichText(
                                              text: TextSpan(
                                                children: [
                                                  TextSpan(
                                                    text: "Volumen: ",
                                                    style: GoogleFonts.roboto(
                                                      fontWeight: FontWeight.bold,
                                                    ),
                                                  ),
                                                  TextSpan(text: _formatearNumeros(_valVolumen)),
                                                ],
                                                style: GoogleFonts.roboto(
                                                  fontSize: 18.0,
                                                ),
                                              ),
                                              maxLines: 1,
                                              overflow: TextOverflow.ellipsis,
                                            ),
                                            const SizedBox(width: 8.0),
                                            DropdownButton<String>(
                                              focusColor: Colors.transparent,
                                              value: _unidadVolumen,
                                              onChanged: (val) => setState(() {
                                                _unidadVolumen = val!;
                                                _confNiveles[_nivelActual]!["unidadVolumen"] = _unidadVolumen;
                                                _calcularVolumen();
                                              }),
                                              items: _unidadesVolumen.map((e) => DropdownMenuItem<String>(
                                                child: Text(
                                                  e,
                                                  style: GoogleFonts.roboto(
                                                    fontSize: 18.0,
                                                  ),
                                                ),
                                                value: e,
                                              )).toList(),
                                            )
                                          ],
                                        ),
                                        const SizedBox(height: 16.0),
                                        Image.asset(
                                          'estacionamiento.png',
                                          width: 156.0,
                                        ),
                                        const SizedBox(height: 16.0),
                                        Container(
                                          margin: const EdgeInsets.symmetric(
                                            horizontal: 32.0,
                                          ),
                                          child: Row(
                                            children: [
                                              Text(
                                                "Normativa:",
                                                style: GoogleFonts.roboto(
                                                  fontWeight: FontWeight.bold,
                                                  fontSize: 18.0,
                                                ),
                                              ),
                                              const SizedBox(width: 8.0),
                                              Expanded(
                                                child: DropdownButton<int>(
                                                  focusColor: Colors.transparent,
                                                  value: _normativa == 0 ? null : _normativa,
                                                  isExpanded: true,
                                                  hint: Text(
                                                    "Selecciona una opción",
                                                    style: GoogleFonts.roboto(
                                                      color: Colors.grey,
                                                      fontSize: 18.0,
                                                      fontStyle: FontStyle.italic,
                                                    ),
                                                  ),
                                                  onChanged: (newVal) => setState(() {
                                                    _normativa = newVal!;
                                                    _confNiveles[_nivelActual]!["normativa"] = _normativas[_normativa];
                                                    _calcularCaudal();

                                                    if(_valDistMax > 0){
                                                      _calcularVelocidad();
                                                    }
                                                  }),
                                                  items: _normativas.keys.map((e) => DropdownMenuItem<int>(
                                                    child: Text(
                                                      _normativas[e]!,
                                                      style: GoogleFonts.roboto(
                                                        fontSize: 18.0,
                                                      ),
                                                    ),
                                                    value: e,
                                                  )).toList(),
                                                ),
                                              )
                                            ],
                                          ),
                                        ),
                                        AnimatedCrossFade(
                                          firstChild: Container(),
                                          secondChild: Column(
                                            children: [
                                              const SizedBox(height: 16.0),
                                              Container(
                                                margin: const EdgeInsets.symmetric(
                                                  horizontal: 32.0,
                                                ),
                                                child: Row(
                                                  children: [
                                                    Expanded(
                                                      child: RichText(
                                                        maxLines: 1,
                                                        overflow: TextOverflow.ellipsis,
                                                        textAlign: TextAlign.center,
                                                        text: TextSpan(
                                                          style: GoogleFonts.roboto(
                                                            fontSize: 18.0,
                                                          ),
                                                          children: [
                                                            TextSpan(
                                                              text: "Caudal Extracción: ",
                                                              style: GoogleFonts.roboto(
                                                                fontWeight: FontWeight.bold,
                                                              ),
                                                            ),
                                                            TextSpan(text: "${_formatearNumeros(_caudalExtraccion)} CFM"),
                                                          ],
                                                        ),
                                                      ),
                                                    ),
                                                    Expanded(
                                                      child: RichText(
                                                        maxLines: 1,
                                                        overflow: TextOverflow.ellipsis,
                                                        textAlign: TextAlign.center,
                                                        text: TextSpan(
                                                          style: GoogleFonts.roboto(
                                                            fontSize: 18.0,
                                                          ),
                                                          children: [
                                                            TextSpan(
                                                              text: "Renovaciones por Segundo: ",
                                                              style: GoogleFonts.roboto(
                                                                fontWeight: FontWeight.bold,
                                                              ),
                                                            ),
                                                            TextSpan(text: "${_renovaciones.toStringAsFixed(4)} ren/s"),
                                                          ],
                                                        ),
                                                      ),
                                                    )
                                                  ],
                                                ),
                                              ),
                                              const SizedBox(height: 16.0),
                                              Container(
                                                margin: const EdgeInsets.symmetric(
                                                  horizontal: 32.0,
                                                ),
                                                child: Row(
                                                  children: [
                                                    Text(
                                                      "Distancia Máxima Recorrida:",
                                                      style: GoogleFonts.roboto(
                                                        fontWeight: FontWeight.bold,
                                                        fontSize: 18.0,
                                                      ),
                                                    ),
                                                    const SizedBox(width: 8.0),
                                                    Expanded(
                                                      child: SizedBox(
                                                        height: 64.0,
                                                        width: double.infinity,
                                                        child: Stack(
                                                          alignment: Alignment.center,
                                                          children: [
                                                            TextField(
                                                              textAlign: TextAlign.center,
                                                              controller: _distMaxController,
                                                              maxLength: 10,
                                                              decoration: const InputDecoration(
                                                                counterText: "",
                                                                counterStyle: TextStyle(
                                                                  height: double.minPositive,
                                                                ),
                                                              ),
                                                              inputFormatters: [
                                                                DecimalTextInputFormatter(),
                                                              ],
                                                              onChanged: (val) {
                                                                if(val.isEmpty){
                                                                  _valDistMax = 0;
                                                                }else{
                                                                  _valDistMax = double.parse(val);
                                                                }

                                                                _confNiveles[_nivelActual]!["distanciaMax"] = _valDistMax;
                                                                _calcularVelocidad();
                                                              },
                                                            ),
                                                            Positioned(
                                                              left: 0.0,
                                                              child: IconButton(
                                                                icon: const Icon(
                                                                  Icons.remove,
                                                                  color: Colors.black45,
                                                                ),
                                                                onPressed: () => setState(() {
                                                                  _valDistMax = _valDistMax - 0.1;

                                                                  if(_valDistMax < 0){
                                                                    _valDistMax = 0.0;
                                                                  }

                                                                  _confNiveles[_nivelActual]!["distanciaMax"] = _valDistMax;
                                                                  _distMaxController.text = _valDistMax.toStringAsFixed(2);
                                                                  _calcularVelocidad();
                                                                }),
                                                              ),
                                                            ),
                                                            Positioned(
                                                              right: 0.0,
                                                              child: IconButton(
                                                                icon: const Icon(
                                                                  Icons.add,
                                                                  color: Colors.black45,
                                                                ),
                                                                onPressed: () => setState(() {
                                                                  _valDistMax = _valDistMax + 0.1;

                                                                  if(_valDistMax > 999){
                                                                    _valDistMax = 999.0;
                                                                  }

                                                                  _confNiveles[_nivelActual]!["distanciaMax"] = _valDistMax;
                                                                  _distMaxController.text = _valDistMax.toStringAsFixed(2);
                                                                  _calcularVelocidad();
                                                                }),
                                                              ),
                                                            ),
                                                          ],
                                                        ),
                                                      ),
                                                    ),
                                                    const SizedBox(width: 8.0),
                                                    Container(
                                                      child: Text(
                                                        _unidadAltura,
                                                        style: GoogleFonts.roboto(
                                                          fontSize: 18.0,
                                                        ),
                                                      ),
                                                      padding: const EdgeInsets.fromLTRB(0, 0, 24.0, 8.0),
                                                      decoration: BoxDecoration(
                                                        border: Border(
                                                          bottom: BorderSide(
                                                              color: Colors.black.withOpacity(0.18),
                                                              width: 2.0
                                                          ),
                                                        ),
                                                      ),
                                                    ),
                                                    const SizedBox(width: 8.0),
                                                    IconButton(
                                                      icon: const Icon(Icons.info_outline),
                                                      onPressed: () => showDialog(
                                                        context: context,
                                                        barrierDismissible: true,
                                                        builder: (context) => const AlertDialog(
                                                          title: Text("Distancia Máxima Recorrida"),
                                                          content: Text("Distancia máxima recorrida por un auto desde que ingresa hasta que localiza un lugar para estacionarse."),
                                                        ),
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                              ),
                                              AnimatedCrossFade(
                                                firstChild: Container(),
                                                secondChild: Column(
                                                  children: [
                                                    const SizedBox(height: 16.0),
                                                    Container(
                                                      margin: const EdgeInsets.symmetric(
                                                        horizontal: 32.0,
                                                      ),
                                                      child: Row(
                                                        children: [
                                                          Expanded(
                                                            child: RichText(
                                                              maxLines: 1,
                                                              overflow: TextOverflow.ellipsis,
                                                              textAlign: TextAlign.center,
                                                              text: TextSpan(
                                                                style: GoogleFonts.roboto(
                                                                  fontSize: 18.0,
                                                                ),
                                                                children: [
                                                                  TextSpan(
                                                                    text: "Velocidad Inducida: ",
                                                                    style: GoogleFonts.roboto(
                                                                      fontWeight: FontWeight.bold,
                                                                    ),
                                                                  ),
                                                                  TextSpan(text: "${_valVelInducida.toStringAsFixed(3)} m/s"),
                                                                ],
                                                              ),
                                                            ),
                                                          ),
                                                          Expanded(
                                                            child: RichText(
                                                              maxLines: 1,
                                                              overflow: TextOverflow.ellipsis,
                                                              textAlign: TextAlign.center,
                                                              text: TextSpan(
                                                                style: GoogleFonts.roboto(
                                                                    fontSize: 18.0
                                                                ),
                                                                children: [
                                                                  TextSpan(
                                                                    text: "Velocidad Recomendada: ",
                                                                    style: GoogleFonts.roboto(
                                                                      fontWeight: FontWeight.bold,
                                                                    ),
                                                                  ),
                                                                  const TextSpan(text: "0.25 m/s"),
                                                                ],
                                                              ),
                                                            ),
                                                          ),
                                                        ],
                                                      ),
                                                    ),
                                                    const SizedBox(height: 16.0),
                                                    Container(
                                                      margin: const EdgeInsets.symmetric(
                                                        horizontal: 32.0,
                                                      ),
                                                      child: Row(
                                                        children: [
                                                          Text(
                                                            "Equipo:",
                                                            style: GoogleFonts.roboto(
                                                              fontWeight: FontWeight.bold,
                                                              fontSize: 18.0,
                                                            ),
                                                          ),
                                                          const SizedBox(width: 8.0),
                                                          Expanded(
                                                            child: DropdownButton<String>(
                                                              focusColor: Colors.transparent,
                                                              value: _equipo,
                                                              isExpanded: true,
                                                              onChanged: (newVal) => setState(() {
                                                                _equipo = newVal!;
                                                                _confNiveles[_nivelActual]!["equipo"] = _equipo;

                                                                _modelo = "";
                                                                _superficieVentilada = 0;

                                                                _confNiveles[_nivelActual]!["modelo"] = "";
                                                                _confNiveles[_nivelActual]!["empuje"] = 0;
                                                              }),
                                                              items: _equipos.map((e) => DropdownMenuItem<String>(
                                                                child: Text(
                                                                  e,
                                                                  style: GoogleFonts.roboto(
                                                                    fontSize: 18.0,
                                                                  ),
                                                                ),
                                                                value: e,
                                                              )).toList(),
                                                            ),
                                                          )
                                                        ],
                                                      ),
                                                    ),
                                                    const SizedBox(height: 16.0),
                                                    Container(
                                                      margin: const EdgeInsets.symmetric(
                                                        horizontal: 32.0,
                                                      ),
                                                      child: Row(
                                                        children: [
                                                          Text(
                                                            "Modelo:",
                                                            style: GoogleFonts.roboto(
                                                              fontWeight: FontWeight.bold,
                                                              fontSize: 18.0,
                                                            ),
                                                          ),
                                                          const SizedBox(width: 8.0),
                                                          Expanded(
                                                            child: DropdownButton<String>(
                                                              focusColor: Colors.transparent,
                                                              value: _modelo.isEmpty ? null : _modelo,
                                                              hint: Text(
                                                                "Selecciona una opción",
                                                                style: GoogleFonts.roboto(
                                                                  color: Colors.grey,
                                                                  fontSize: 18.0,
                                                                  fontStyle: FontStyle.italic,
                                                                ),
                                                              ),
                                                              isExpanded: true,
                                                              onChanged: (newVal) => setState(() {
                                                                _modelo = newVal!;

                                                                _confNiveles[_nivelActual]!["modelo"] = _modelo;
                                                                _confNiveles[_nivelActual]!["empuje"] = _listaEquipos[_equipo]![_modelo];
                                                                _confNiveles[_nivelActual]!["equipoIMG"] = _listaEquiposImagen[_equipo] == null
                                                                  ? "" : "${_listaEquiposImagen[_equipo]![_modelo]}.jpg";

                                                                _calcularSuperficieVentilada();
                                                              }),
                                                              items: _listaEquipos[_equipo]!.keys.map((e) => DropdownMenuItem<String>(
                                                                child: Text(
                                                                  e,
                                                                  style: GoogleFonts.roboto(
                                                                    fontSize: 18.0,
                                                                  ),
                                                                ),
                                                                value: e,
                                                              )).toList(),
                                                            ),
                                                          ),
                                                        ],
                                                      ),
                                                    ),
                                                    AnimatedCrossFade(
                                                      firstChild: Container(),
                                                      secondChild: Column(
                                                        children: [
                                                          const SizedBox(height: 16.0),
                                                          Container(
                                                            margin: const EdgeInsets.symmetric(
                                                              horizontal: 32.0,
                                                            ),
                                                            child: Row(
                                                              children: [
                                                                Expanded(
                                                                  child: RichText(
                                                                    maxLines: 1,
                                                                    overflow: TextOverflow.ellipsis,
                                                                    textAlign: TextAlign.center,
                                                                    text: TextSpan(
                                                                      style: GoogleFonts.roboto(
                                                                        fontSize: 18.0,
                                                                      ),
                                                                      children: [
                                                                        TextSpan(
                                                                          text: "Empuje(N): ",
                                                                          style: GoogleFonts.roboto(
                                                                            fontWeight: FontWeight.bold,
                                                                          ),
                                                                        ),
                                                                        TextSpan(text: "${_listaEquipos[_equipo]![_modelo]}"),
                                                                      ],
                                                                    ),
                                                                  ),
                                                                ),
                                                                Expanded(
                                                                  child: RichText(
                                                                    maxLines: 1,
                                                                    overflow: TextOverflow.ellipsis,
                                                                    textAlign: TextAlign.center,
                                                                    text: TextSpan(
                                                                      style: GoogleFonts.roboto(
                                                                        fontSize: 18.0,
                                                                      ),
                                                                      children: [
                                                                        TextSpan(
                                                                          text: "Constante (K): ",
                                                                          style: GoogleFonts.roboto(
                                                                            fontWeight: FontWeight.bold,
                                                                          ),
                                                                        ),
                                                                        const TextSpan(text: "0.54"),
                                                                      ],
                                                                    ),
                                                                  ),
                                                                ),
                                                                Expanded(
                                                                  child: RichText(
                                                                    maxLines: 1,
                                                                    overflow: TextOverflow.ellipsis,
                                                                    textAlign: TextAlign.center,
                                                                    text: TextSpan(
                                                                      style: GoogleFonts.roboto(
                                                                        fontSize: 18.0,
                                                                      ),
                                                                      children: [
                                                                        TextSpan(
                                                                          text: "V²: ",
                                                                          style: GoogleFonts.roboto(
                                                                            fontWeight: FontWeight.bold,
                                                                          ),
                                                                        ),
                                                                        //TextSpan(text: "${math.pow(_valVelInducida < 0.3 ? 0.3 : _valVelInducida, 2).toStringAsFixed(3)} m²/s²"),
                                                                        TextSpan(text: "${math.pow(_valVelInducida, 2).toStringAsFixed(3)} m²/s²"),
                                                                      ],
                                                                    ),
                                                                  ),
                                                                )
                                                              ],
                                                            ),
                                                          ),
                                                          const SizedBox(height: 16.0),
                                                          Container(
                                                            margin: const EdgeInsets.symmetric(
                                                              horizontal: 32.0,
                                                            ),
                                                            child: Row(
                                                              children: [
                                                                Expanded(
                                                                  child: RichText(
                                                                    maxLines: 1,
                                                                    overflow: TextOverflow.ellipsis,
                                                                    textAlign: TextAlign.center,
                                                                    text: TextSpan(
                                                                        style: GoogleFonts.roboto(
                                                                          fontSize: 18.0,
                                                                        ),
                                                                        children: [
                                                                          TextSpan(
                                                                            text: "Superficie Ventilada: ",
                                                                            style: GoogleFonts.roboto(
                                                                              fontWeight: FontWeight.bold,
                                                                            ),
                                                                          ),
                                                                          TextSpan(text: "${_superficieVentilada.toStringAsFixed(2)} m²"),
                                                                        ]
                                                                    ),
                                                                  ),
                                                                ),
                                                                Expanded(
                                                                  child: RichText(
                                                                    maxLines: 1,
                                                                    overflow: TextOverflow.ellipsis,
                                                                    textAlign: TextAlign.center,
                                                                    text: TextSpan(
                                                                      style: GoogleFonts.roboto(
                                                                        fontSize: 18.0,
                                                                      ),
                                                                      children: [
                                                                        TextSpan(
                                                                          text: "Equipos: ",
                                                                          style: GoogleFonts.roboto(
                                                                            fontWeight: FontWeight.bold,
                                                                          ),
                                                                        ),
                                                                        TextSpan(text: _cantEquipos.toStringAsFixed(2)),
                                                                      ],
                                                                    ),
                                                                  ),
                                                                ),
                                                              ],
                                                            ),
                                                          ),
                                                          const SizedBox(height: 16.0),
                                                          Container(
                                                            margin: const EdgeInsets.symmetric(
                                                              horizontal: 32.0,
                                                            ),
                                                            child: Text(
                                                              "Cantidad de Equipos TOTAL: $_intEquipos EQUIPO(S)",
                                                              textAlign: TextAlign.center,
                                                              style: GoogleFonts.roboto(
                                                                fontSize: 18.0,
                                                                fontWeight: FontWeight.bold,
                                                              ),
                                                            ),
                                                          ),
                                                        ],
                                                      ),
                                                      duration: const Duration(milliseconds: 250),
                                                      crossFadeState: _superficieVentilada == 0 ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                                                    )
                                                  ],
                                                ),
                                                duration: const Duration(milliseconds: 250),
                                                crossFadeState: _valDistMax == 0 ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                                              )
                                            ],
                                          ),
                                          duration: const Duration(milliseconds: 250),
                                          crossFadeState: _caudalExtraccion == 0 ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                                        )
                                      ],
                                    ),
                                    duration: const Duration(milliseconds: 250),
                                    crossFadeState: _valVolumen == 0 || _ciudad.isEmpty || _estado.isEmpty || _tempCiudad == 0 || _alturaCiudad == 0
                                        ? CrossFadeState.showFirst : CrossFadeState.showSecond,
                                  ),
                                ],
                              ),
                            ),
                          ),
                          options: CarouselOptions(
                            enableInfiniteScroll: false,
                            onPageChanged: (index, options) => setState((){
                              _nivelActual = index + 1;
                              _initVariables(_confNiveles[index + 1]!);
                            }),
                            height: double.infinity,
                            viewportFraction: 1.0,
                          ),
                          carouselController: _carouselController,
                        ),
                        Positioned(
                          left: 0.0,
                          child: MaterialButton(
                            elevation: 4.0,
                            hoverElevation: 8.0,
                            padding: const EdgeInsets.all(4.0),
                            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                            color: Colors.white,
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(18.0),
                            ),
                            minWidth: 0,
                            child: const Icon(
                              Icons.keyboard_arrow_left,
                              size: 32.0,
                            ),
                            onPressed: _nivelActual == 1 ? null : () => _carouselController.previousPage(
                              duration: const Duration(milliseconds: 500),
                            ),
                          ),
                        ),
                        Positioned(
                          right: 0.0,
                          child: MaterialButton(
                            elevation: 4.0,
                            hoverElevation: 8.0,
                            padding: const EdgeInsets.all(4.0),
                            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                            color: Colors.white,
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(18.0),
                            ),
                            minWidth: 0,
                            child: const Icon(
                              Icons.keyboard_arrow_right,
                              size: 32.0,
                            ),
                            onPressed: _nivelActual == _valNiveles ? null : () => _carouselController.nextPage(
                              duration: const Duration(milliseconds: 500),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
                const SizedBox(height: 32.0),
                Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 32.0,
                  ),
                  child: Row(
                    children: [
                      Expanded(
                        child: MaterialButton(
                          elevation: 4,
                          padding: const EdgeInsets.symmetric(vertical: 16.0),
                          minWidth: (containerWidth / 2) - 32,
                          color: const Color(0xFFFF0000),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Image.asset(
                                "guardar.png",
                                width: 32.0,
                              ),
                              const SizedBox(width: 8.0),
                              const Text(
                                "Guardar y regresar",
                                style: TextStyle(
                                  fontFamily: "Helvetica Neue Black Cond",
                                  color: Colors.white,
                                  fontSize: 28.0,
                                ),
                              )
                            ],
                          ),
                          onPressed: () async{
                            final Map<String, String> niveles = {};
                            _confNiveles.forEach((key, value) {
                              final Map<String, String> nivel = {};
                              value.forEach((key0, value0) {
                                if(value0.runtimeType == String){
                                  nivel[key0] = value0;
                                }else{
                                  nivel[key0] = "$value0";
                                }
                              });

                              final nivelStr = base64.encode(utf8.encode(jsonEncode(nivel)));
                              niveles["$key"] = nivelStr;
                            });

                            Map<String, Map<String, String>> info = {
                              "ubicacion": {
                                "region": _continenteAct,
                                "pais": _paisConf,
                                "estado": _estado,
                                "ciudad": _ciudad,
                                "ubiStr": _ubicacion,
                              },
                              "datos": {
                                "temperatura": "$_tempCiudad",
                                "altura": "$_alturaCiudad",
                                "cantNiveles": "$_valNiveles",
                                "densidad": "$_densidad",
                              },
                              "niveles": niveles,
                            };

                            final infoStr = jsonEncode(info);
                            final guardado = await _cambiarDatos(infoStr, "", _finalizado ? "F" : "C");
                            if(guardado){
                              Navigator.pop(context);
                            }else{
                              Fluttertoast.showToast(
                                msg: "Hubo un error al intentar guardar el proyecto, intentelo de nuevo más tarde.",
                                toastLength: Toast.LENGTH_SHORT,
                                timeInSecForIosWeb: 4,
                                gravity: ToastGravity.CENTER,
                                webBgColor: "linear-gradient(to right, #b40404, #ff0000)",
                              );
                            }
                          },
                        ),
                      ),
                      const SizedBox(width: 16.0),
                      Expanded(
                        child: MaterialButton(
                          elevation: 4,
                          padding: const EdgeInsets.symmetric(vertical: 16.0),
                          minWidth: (containerWidth/2)-32,
                          color: const Color(0xFFFF0000),
                          disabledColor: Colors.grey,
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: const [
                              Icon(
                                Icons.print,
                                color: Colors.white,
                                size: 32.0,
                              ),
                              SizedBox(width: 8.0),
                              Text(
                                "Imprimir resultados",
                                style: TextStyle(
                                  fontFamily: "Helvetica Neue Black Cond",
                                  color: Colors.white,
                                  fontSize: 28.0,
                                ),
                              ),
                            ],
                          ),
                          onPressed: _finalizado ? () async{
                            final ruta = {
                              "idUsuario": widget.idUsuario,
                              "idProyecto": widget.idProyecto,
                              "noProyecto": widget.noProyecto
                            };

                            final rutab64 = base64Encode(utf8.encode(jsonEncode(ruta)));

                            final Map<String, String> niveles = {};
                            _confNiveles.forEach((key, value) {
                              final Map<String, String> nivel = {};
                              value.forEach((key0, value0) {
                                if(value0.runtimeType == String){
                                  nivel[key0] = value0;
                                }else{
                                  nivel[key0] = "$value0";
                                }
                              });

                              final nivelStr = base64.encode(utf8.encode(jsonEncode(nivel)));
                              niveles["$key"] = nivelStr;
                            });

                            Map<String, Map<String, String>> info = {
                              "ubicacion": {
                                "region": _continenteAct,
                                "pais": _paisConf,
                                "estado": _estado,
                                "ciudad": _ciudad,
                                "ubiStr": _ubicacion,
                              },
                              "datos": {
                                "temperatura": "$_tempCiudad",
                                "altura": "$_alturaCiudad",
                                "cantNiveles": "$_valNiveles",
                                "densidad": "$_densidad",
                              },
                              "niveles": niveles,
                            };

                            final infoStr = jsonEncode(info);

                            final infoPDF = base64Encode(utf8.encode(jsonEncode({
                              "ruta": rutab64,
                              "infoCalculo": base64Encode(utf8.encode(infoStr))
                            })));

                            final urlArch = await _pdfProvider.fetchAtenuador(infoPDF, 'estacionamiento');

                            html.AnchorElement anchorElement = html.AnchorElement(href: urlArch);
                            anchorElement.download = urlArch;
                            anchorElement.target = "_blank";
                            anchorElement.click();

                            final guardado = await _cambiarDatos(infoStr, urlArch, _finalizado ? "F" : "C");
                            if(!guardado){
                              Fluttertoast.showToast(
                                msg: "Hubo un error al intentar guardar el proyecto, intentelo de nuevo más tarde.",
                                toastLength: Toast.LENGTH_SHORT,
                                timeInSecForIosWeb: 4,
                                gravity: ToastGravity.CENTER,
                                webBgColor: "linear-gradient(to right, #b40404, #ff0000)",
                              );
                            }
                          } : null ,
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 32.0),
              ],
            ),
          );
        },
      ),
    );
  }

  bool _finalizar(){
    int cont = 0;

    _confNiveles.forEach((key, value) {
      final equiposTot = value["equiposTot"].runtimeType == String ? int.parse(value["equiposTot"]) : value["equiposTot"];
      if(equiposTot == 0) return;
      cont++;
    });

    return cont == _confNiveles.length;
  }

  void _calcularVolumen() => setState(() {
    if(_valAltura != 0 && _valArea != 0){
      if(_unidadVolumen == "m³"){
        if(_unidadArea == "m²" && _unidadAltura == "m"){
          _valVolumen = _valAltura * _valArea;
        }else if(_unidadArea == "ft²" && _unidadAltura == "m"){
          double conversion = _valArea / 10.764;
          _valVolumen = _valAltura * conversion;
        }else if(_unidadArea == "m²" && _unidadAltura == "ft"){
          double conversion = _valAltura / 3.281;
          _valVolumen = _valArea * conversion;
        }else{
          double conversion1 = _valArea / 10.764;
          double conversion2 = _valAltura / 3.281;
          _valVolumen = conversion1 * conversion2;
        }
      }else{
        if(_unidadArea == "m²" && _unidadAltura == "m"){
          double conversion1 = _valArea * 10.764;
          double conversion2 = _valAltura * 3.281;
          _valVolumen = conversion1 * conversion2;
        }else if(_unidadArea == "ft²" && _unidadAltura == "m"){
          double conversion = _valAltura * 3.281;
          _valVolumen = _valAltura * conversion;
        }else if(_unidadArea == "m²" && _unidadAltura == "ft"){
          double conversion = _valArea * 10.764;
          _valVolumen = _valArea * conversion;
        }else{
          _valVolumen = _valAltura * _valArea;
        }
      }

      if(_normativa > 0) _calcularCaudal();
    }else{
      _valVolumen = 0;
    }

    _confNiveles[_nivelActual]!["volumen"] = _valVolumen;
  });

  void _calcularCaudal() => setState(() {
    switch(_normativa){
      case 1:
        double area = _unidadArea == "m²" ? _valArea * 10.76391041671 : _valArea;
        _caudalExtraccion = area * 0.75;

        double volumen = _unidadVolumen == "ft³" ? _valVolumen / 35.3147 : _valVolumen;
        _renovaciones = (_caudalExtraccion * 0.0004719474432) / volumen;
        break;
      case 2:
        double area = _unidadArea == "m²" ? _valArea * 10.76391041671 : _valArea;
        _caudalExtraccion = area;

        double volumen = _unidadVolumen == "ft³" ? _valVolumen / 35.3147 : _valVolumen;
        _renovaciones = (_caudalExtraccion * 0.0004719474432) / volumen;
        break;
      case 3:
        double volumen = _unidadVolumen == "ft³" ? _valVolumen * 0.028316846592 : _valVolumen;
        //Se calcula el caudal multiplicado el volumen por las renovaciones
        double caudal = volumen * 10;
        //Se convierte de metros cubicos por hora a metros cubicos por segundo
        _caudalExtraccion = caudal * 0.5885783314180995;
        _renovaciones = 10 / 3600;
        break;
    }

    _confNiveles[_nivelActual]!["caudal"] = _caudalExtraccion;
    _confNiveles[_nivelActual]!["renovaciones"] = _renovaciones;

    if(_valDistMax > 0){
      _calcularVelocidad();
    }
  });

  void _calcularVelocidad() => setState(() {
    if(_valDistMax > 0){
      _valVelInducida = _valDistMax * _renovaciones;
      _confNiveles[_nivelActual]!["velInd"] = _valVelInducida;

      if(_modelo.isNotEmpty){
        _calcularSuperficieVentilada();
      }
    }
  });

  void _calcularSuperficieVentilada() => setState(() {
    final empuje = _listaEquipos[_equipo]![_modelo];
    const k = 0.54;
    //final velInd = math.pow(_valVelInducida < 0.3 ? 0.3 : _valVelInducida, 2);
    final velInd = math.pow(_valVelInducida, 2);
    _confNiveles[_nivelActual]!["V2"] = velInd;

    _superficieVentilada = empuje! / (k * _densidad * velInd);
    _cantEquipos = _valArea / _superficieVentilada;

    _confNiveles[_nivelActual]!["supVent"] = _superficieVentilada;
    _confNiveles[_nivelActual]!["equipos"] = _cantEquipos;

    int equiposInt = _cantEquipos.toInt();
    double fraccion = _cantEquipos - equiposInt;

    _intEquipos = fraccion > 0.0 ? equiposInt + 1 : equiposInt;
    _confNiveles[_nivelActual]!["equiposTot"] = _intEquipos;

    _finalizado = _finalizar();
  });
  
  String _formatearNumeros(double numero){
    final numArr = numero.toStringAsFixed(2).split(".");
    final entero = numArr[0];

    final enteroArr = entero.split("").reversed.toList();
    String formatted = "";

    for(int i = 0; i < enteroArr.length; i++){
      if(i % 3 == 2 && i < enteroArr.length - 1){
        formatted = ",${enteroArr[i]}$formatted";
      }else{
        formatted = "${enteroArr[i]}$formatted";
      }
    }

    return "$formatted.${numArr.last}";
  }
}
