import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/domain/entities/carton_size.dart';
import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/domain/vo/delivery_address.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/carton/carton_package_table.dart';
import 'package:fcs/pages/carton_search/carton_search.dart';
import 'package:fcs/pages/carton_size/carton_size_list.dart';
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/package/model/package_model.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/user_search/user_serach.dart';
import 'package:fcs/pages/widgets/defalut_delivery_address.dart';
import 'package:fcs/pages/widgets/delivery_address_selection.dart';
import 'package:fcs/pages/widgets/display_text.dart';
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
import 'package:fcs/pages/widgets/length_picker.dart';
import 'package:fcs/pages/widgets/local_button.dart';
import 'package:fcs/pages/widgets/local_dropdown.dart';
import 'package:fcs/pages/widgets/local_radio_buttons.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart';
import 'cargo_type_addtion.dart';
import 'carton_cargo_table.dart';
import 'carton_row.dart';
import 'model/carton_model.dart';
import '../carton_size/model/carton_size_model.dart';
import 'package_carton_editor.dart';
import 'widgets.dart';

class CartonEditor extends StatefulWidget {
  final Carton? carton;
  CartonEditor({this.carton});

  @override
  _CartonEditorState createState() => _CartonEditorState();
}

class _CartonEditorState extends State<CartonEditor> {
  TextEditingController _widthController = new TextEditingController();
  TextEditingController _heightController = new TextEditingController();
  TextEditingController _lengthController = new TextEditingController();
  DeliveryAddress? _deliveryAddress = new DeliveryAddress();
  List<CargoType> _cargoTypes = [];

  Carton? _carton;
  bool _isLoading = false;
  bool _isNew = false;
  User? _user;
  String? _selectedCartonType;

  double volumetricRatio = 0;
  double shipmentWeight = 0;
  FcsShipment? _fcsShipment;
  List<FcsShipment> _fcsShipments = [];
  List<Carton> _cartons = [];
  CartonSize? selectedCatonSize;

  //for mix carton
  List<Carton> _mixCartons = [];
  String? _selectedMixBoxType;

  //for carton from cargos
  User? consignee;
  User? sender;
  List<Carton> _cartonsFromCartons = [];

  double? totalWeight;

  @override
  void initState() {
    super.initState();

    //for shipment weight
    volumetricRatio = Provider.of<ShipmentRateModel>(context, listen: false)
        .rate
        .volumetricRatio;
    _lengthController.addListener(_calShipmentWeight);
    _widthController.addListener(_calShipmentWeight);
    _heightController.addListener(_calShipmentWeight);

    if (widget.carton != null) {
      _carton = widget.carton;
      _deliveryAddress = _carton!.deliveryAddress;
      _widthController.text = _carton!.width.toString();
      _heightController.text = _carton!.height.toString();
      _lengthController.text = _carton!.length.toString();
      _selectedCartonType = _carton!.cartonType;

      _cargoTypes = _carton!.cargoTypes.map((e) => e.clone()).toList();

      _isNew = false;
      _user = User(
          id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
      consignee = User(
          id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
      sender = User(
          id: _carton!.senderID,
          fcsID: _carton!.senderFCSID,
          name: _carton!.senderName);
      _selectedMixBoxType = _carton!.mixBoxType;
      this._mixCartons =
          _carton!.mixCartons == null ? [] : List.from(_carton!.mixCartons);
      bool isMixBox = _carton!.cartonType == carton_mix_box;
      bool isFromPackages = _carton!.cartonType == carton_from_packages;
      if (isFromPackages) _loadPackages();

      if (!isMixBox) {
        _getCartonSize();
      }
    } else {
      _carton = Carton(
        cargoTypes: [],
        packages: [],
      );
      _lengthController.text = "0";
      _widthController.text = "0";
      _heightController.text = "0";
      _isNew = true;
      _selectedCartonType = carton_from_packages;
      _selectedMixBoxType = mix_delivery;
      _loadFcsShipments();
    }
  }

  _loadFcsShipments() async {
    FcsShipmentModel fcsShipmentModel =
        Provider.of<FcsShipmentModel>(context, listen: false);
    var fcsShipments = await fcsShipmentModel.getActiveFcsShipments();

    // var fcsShipment =
    //     fcsShipments.firstWhere((e) => e.id == _carton?.fcsShipmentID);

    setState(() {
      _fcsShipments = fcsShipments;
      // _fcsShipment = fcsShipment;
    });
  }

  _loadPackages() async {
    if (_user == null) return;
    PackageModel packageModel =
        Provider.of<PackageModel>(context, listen: false);
    List<Package> packages = await packageModel.getPackages(
        _user!.id!, [package_processed_status, package_packed_status]);
    if (_isNew) {
      String? prevCompare;
      packages.forEach((p) {
        String compare = (p.deliveryAddress?.fullName ?? "") +
            (p.deliveryAddress?.phoneNumber ?? "");
        if (prevCompare != null && compare == prevCompare) {
          p.isChecked = true;
        } else {
          p.isChecked = false;
        }
        if (prevCompare == null) {
          p.isChecked = true;
          prevCompare = compare;
        }
      });
    } else {
      packages.forEach((p) {
        if (_carton!.packages.contains(p)) {
          p.isChecked = _carton!.packages.firstWhere((cp) => cp == p).isChecked;
        } else {
          p.isChecked = false;
        }
      });
    }

    setState(() {
      _carton!.packages = packages;
    });
    // _populateDeliveryAddress();
  }

  // _populateDeliveryAddress() {
  //   if (_carton.packages == null) return;
  //   var d = _carton.packages
  //       .firstWhere((p) => p.isChecked && p.deliveryAddress != null,
  //           orElse: () => null)
  //       ?.deliveryAddress;
  //   setState(() {
  //     _deliveryAddress = d;
  //   });
  // }

  _calShipmentWeight() {
    double l = double.tryParse(_lengthController.text) ?? 0;
    double w = double.tryParse(_widthController.text) ?? 0;
    double h = double.tryParse(_heightController.text) ?? 0;
    setState(() {
      shipmentWeight = l * w * h / volumetricRatio;
    });
  }

  _getCartonSize() {
    var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false);
    cartonSizeModel.cartonSizes.forEach((c) {
      if (c.length == _carton!.length &&
          c.width == _carton!.width &&
          c.height == _carton!.height) {
        selectedCatonSize = CartonSize(
            id: c.id,
            name: c.name,
            length: c.length,
            width: c.width,
            height: c.height);
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var boxModel = Provider.of<CartonModel>(context);
    bool isFromPackages = _selectedCartonType == carton_from_packages;
    bool isFromCartons = _selectedCartonType == carton_from_cartons;
    bool isMixBox = _selectedCartonType == carton_mix_box;

    final shipmentBox = DisplayText(
      text: _carton!.fcsShipmentNumber,
      labelTextKey: "box.fcs_shipment_num",
      iconData: Ionicons.ios_airplane,
    );

    var fcsShipmentsBox = Container(
        padding: EdgeInsets.only(top: 10),
        child: LocalDropdown<FcsShipment>(
          callback: (v) {
            setState(() {
              _fcsShipment = v;
            });
          },
          labelKey: "shipment.pack.fcs.shipment",
          iconData: Ionicons.ios_airplane,
          display: (u) => u.shipmentNumber,
          selectedValue: _fcsShipment,
          values: _fcsShipments,
        ));

    final fcsIDBox = Container(
        padding: EdgeInsets.only(top: 15),
        child: Row(
          children: <Widget>[
            Expanded(
                child: DisplayText(
              text: _user?.fcsID ?? "",
              labelTextKey: "box.fcs.id",
              icon: FcsIDIcon(),
            )),
            _isNew
                ? IconButton(
                    icon: Icon(Icons.search, color: primaryColor),
                    onPressed: () => searchUser(context, onUserSelect: (u) {
                          setState(() {
                            this._user = u;
                            _loadPackages();
                          });
                        }, popPage: true))
                : Container(),
          ],
        ));

    final namebox = DisplayText(
      text: _user?.name ?? "",
      labelTextKey: "box.name",
      iconData: Icons.person,
    );

    final createBtn = LocalButton(
      textKey: "box.complete.packaging",
      callBack: () {
        Navigator.pop(context);
      },
    );

    final saveBtn = LocalButton(
      textKey: "box.cargo.save.btn",
      callBack: _save,
    );

    final cartonTypeBox = LocalRadioButtons(
        readOnly: !_isNew,
        values: boxModel.cartonTypes,
        selectedValue: _selectedCartonType,
        callback: (String? v) {
          setState(() {
            _selectedCartonType = v;
          });
        });

    final cartonTitleBox = Container(
      child: LocalTitle(
        textKey: "boxes.title",
        trailing: IconButton(
            icon: Icon(
              Icons.add_circle,
              color: primaryColor,
            ),
            onPressed: _addCarton),
      ),
    );

    final mixTypeBox = Container(
      padding: EdgeInsets.only(top: 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
              padding: EdgeInsets.only(left: 5),
              child: LocalText(
                context,
                "box.mix_type",
                color: primaryColor,
                fontSize: 15,
                fontWeight: FontWeight.bold,
              )),
          Row(
            children: boxModel.mixBoxTypes.map((e) {
              return Row(
                children: [
                  Radio(
                    value: e,
                    groupValue: _selectedMixBoxType,
                    activeColor: primaryColor,
                    onChanged: (String? v) {
                      setState(() {
                        _selectedMixBoxType = v;
                      });
                    },
                  ),
                  Text(e),
                ],
              );
            }).toList(),
          ),
        ],
      ),
    );

    final mixTypeDisplayBox = Container(
      padding: EdgeInsets.only(top: 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
              padding: EdgeInsets.only(left: 5),
              child: LocalText(
                context,
                "box.mix_type",
                color: primaryColor,
                fontSize: 15,
                fontWeight: FontWeight.bold,
              )),
          Row(
            children: [
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(
                  Icons.check,
                  color: primaryColor,
                ),
              ),
              Text(_selectedMixBoxType ?? "")
            ],
          )
        ],
      ),
    );

    final mixcartonTitleBox = Container(
      child: LocalTitle(
        textKey: "box.mix_caton_title",
        trailing: IconButton(
          icon: Icon(
            Icons.add_circle,
            color: primaryColor,
          ),
          onPressed: () async {
            boxModel.selectedIndexFilter = 1;
            searchCarton(context, callbackCartonSelect: (c) {
              _addMixCarton(c);
            });
          },
        ),
      ),
    );
    final cargoTableTitleBox = LocalTitle(
      textKey: "box.cargo.type",
      trailing: IconButton(
          icon: Icon(
            Icons.add_circle,
            color: primaryColor,
          ),
          onPressed: () async {
            List<CargoType>? cargos = await Navigator.push<List<CargoType>>(
                context,
                CupertinoPageRoute(builder: (context) => CargoTypeAddition()));
            if (cargos == null) return;
            setState(() {
              _cargoTypes.addAll(
                  cargos.where((e) => !_cargoTypes.contains(e)).toList());
            });
          }),
    );

    final cargoTableBox = CargoTable(
      isNew: _isNew,
      cargoTypes: _cargoTypes,
      onRemove: (c) => _removeCargo(c),
      onUpdate: (c) => _updateCargo(c),
    );

    final lengthBox = LengthPicker(
      controller: _lengthController,
      lableKey: "box.length",
      isReadOnly: false,
    );
    final widthBox = LengthPicker(
      controller: _widthController,
      lableKey: "box.width",
      isReadOnly: false,
    );
    final heightBox = LengthPicker(
      controller: _heightController,
      lableKey: "box.height",
      isReadOnly: false,
    );
    final dimBox = Row(
      mainAxisAlignment: MainAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.only(right: 8.0),
          child: Icon(FontAwesome.arrow_circle_right, color: primaryColor),
        ),
        SizedBox(child: lengthBox, width: 80),
        SizedBox(child: widthBox, width: 80),
        SizedBox(child: heightBox, width: 80),
      ],
    );

    final createMixCarton = LocalButton(
      textKey: _isNew ? "box.mix_carton_btn" : "box.mix_carton.update.btn",
      callBack: _creatMixCarton,
    );

    final consigneefcsIDBox = Row(
      children: <Widget>[
        Expanded(
            child: DisplayText(
          text: consignee != null ? consignee!.fcsID : "",
          labelTextKey: "processing.fcs.id",
          icon: FcsIDIcon(),
        )),
        IconButton(
            icon: Icon(Icons.search, color: primaryColor),
            onPressed: () => searchUser(context, onUserSelect: (u) {
                  setState(() {
                    this.consignee = u;
                  });
                }, popPage: true)),
      ],
    );

    final consigneeNameBox = DisplayText(
      text: consignee != null ? consignee!.name : "",
      labelTextKey: "processing.consignee.name",
      maxLines: 2,
      iconData: Icons.person,
    );

    final consigneeBox = Container(
      child: Column(
        children: [
          consigneefcsIDBox,
          consigneeNameBox,
        ],
      ),
    );

    final shipperIDBox = Row(
      children: <Widget>[
        Expanded(
            child: DisplayText(
          text: sender != null ? sender!.fcsID : "",
          labelTextKey: "processing.fcs.id",
          icon: FcsIDIcon(),
        )),
        IconButton(
            icon: Icon(Icons.search, color: primaryColor),
            onPressed: () => searchUser(context, onUserSelect: (u) {
                  setState(() {
                    this.sender = u;
                  });
                }, popPage: true)),
      ],
    );

    final shipperNamebox = DisplayText(
      text: sender != null ? sender!.name : "",
      labelTextKey: "processing.shipper.name",
      maxLines: 2,
      iconData: Icons.person,
    );

    final shipperBox = Container(
      child: Column(
        children: [
          shipperIDBox,
          shipperNamebox,
        ],
      ),
    );

    return LocalProgress(
      inAsyncCall: _isLoading,
      child: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          leading: new IconButton(
              icon:
                  new Icon(CupertinoIcons.back, color: primaryColor, size: 30),
              onPressed: () => Navigator.of(context).pop()),
          shadowColor: Colors.transparent,
          backgroundColor: Colors.white,
          title: LocalText(
            context,
            _isNew ? "box.info.title" : "box.edit.title",
            fontSize: 20,
            color: primaryColor,
          ),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: ListView(
            shrinkWrap: true,
            children: [
              _isNew
                  ? Container()
                  : Center(child: getCartonNumberStatus(context, _carton!)),
              LocalTitle(textKey: "box.type.title"),
              cartonTypeBox,
              LocalTitle(textKey: "box.shipment_info"),
              _isNew ? fcsShipmentsBox : shipmentBox,
              isMixBox
                  ? _isNew
                      ? mixTypeBox
                      : mixTypeDisplayBox
                  : Container(),
              ...(isMixBox
                  ? [
                      mixcartonTitleBox,
                      Column(
                          children: _getMixCartons(context, this._mixCartons)),
                    ]
                  : [
                      isFromPackages ? fcsIDBox : Container(),
                      isFromPackages ? namebox : Container(),
                      isFromPackages
                          ? CartonPackageTable(
                              packages: _carton!.packages,
                              onSelect: (p, checked) {
                                // if (checked &&
                                //     _deliveryAddress != null &&
                                //     p.deliveryAddress?.id !=
                                //         _deliveryAddress.id) {
                                //   return;
                                // }
                                setState(() {
                                  p.isChecked = checked;
                                });
                                // _populateDeliveryAddress();
                              },
                            )
                          : Container(),
                      isFromCartons
                          ? Container(
                              padding: const EdgeInsets.only(top: 15),
                              child: Row(
                                children: [
                                  Flexible(child: consigneeBox),
                                  Flexible(child: shipperBox)
                                ],
                              ),
                            )
                          : Container(),
                      _isNew ? cartonTitleBox : Container(),
                      _isNew
                          ? Column(
                              children: _getCartons(
                                  context,
                                  isFromPackages
                                      ? this._cartons
                                      : this._cartonsFromCartons))
                          : Container(),
                      _isNew ? Container() : cargoTableTitleBox,
                      _isNew ? Container() : cargoTableBox,
                      _isNew
                          ? Container()
                          : LocalTitle(textKey: "box.dimension"),
                      _isNew ? Container() : cartonSizeDropdown(),
                      _isNew ? Container() : dimBox,
                      _isNew
                          ? Container()
                          : LocalTitle(textKey: "box.delivery_address"),
                      _isNew
                          ? Container()
                          : DefaultDeliveryAddress(
                              deliveryAddress: _deliveryAddress,
                              labelKey: "box.delivery_address",
                              onTap: () async {
                                DeliveryAddress? d =
                                    await Navigator.push<DeliveryAddress>(
                                  context,
                                  CupertinoPageRoute(
                                      builder: (context) =>
                                          DeliveryAddressSelection(
                                              deliveryAddress: _deliveryAddress,
                                              user: User(
                                                  id: _carton!.userID,
                                                  name: _carton!.userName))),
                                );
                                if (d == null) return;
                                setState(() {
                                  _deliveryAddress = d;
                                });
                              }),
                    ]),
              SizedBox(
                height: 20,
              ),
              isFromPackages || isFromCartons
                  ? _isNew
                      ? createBtn
                      : saveBtn
                  : Container(),
              isMixBox ? createMixCarton : Container(),
              SizedBox(
                height: 20,
              ),
            ],
          ),
        ),
      ),
    );
  }

  List<Widget> _getCartons(BuildContext context, List<Carton> cartons) {
    return cartons.asMap().entries.map((c) {
      return InkWell(
        onTap: () async {
          bool isFromPackages = _selectedCartonType == carton_from_packages;
          bool isFromCartons = _selectedCartonType == carton_from_cartons;
          if (isFromPackages) {
            _loadPackages();
            c.value.packages = _carton!.packages;
            Carton _c = await Navigator.push(
              context,
              CupertinoPageRoute(
                  builder: (context) => PackageCartonEditor(
                        carton: c.value,
                        isNew: false,
                        consignee: _user,
                      )),
            );
            if (_c == null) return;
            cartons.removeWhere((item) => item.id == _c.id);
            cartons.insert(c.key, _c);
            setState(() {});
          }
        },
        child: CartonRow(
          key: ValueKey(c.value.id),
          box: c.value,
        ),
      );
    }).toList();
  }

  List<Widget> _getMixCartons(BuildContext context, List<Carton> cartons) {
    return cartons.map((c) {
      return CartonRow(
        key: ValueKey(c.id),
        box: c,
        onRemove: (carton) {
          _removeMixCarton(carton);
        },
      );
    }).toList();
  }

  Widget cartonSizeDropdown() {
    List<CartonSize> _cartonSizes =
        Provider.of<CartonSizeModel>(context).getCartonSizes;

    return Padding(
      padding: const EdgeInsets.only(top: 10),
      child: Row(
        children: [
          Padding(
            padding: const EdgeInsets.only(left: 0, right: 10),
            child: Icon(AntDesign.CodeSandbox, color: primaryColor),
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.only(right: 18.0),
                  child: LocalText(
                    context,
                    "box.carton_size",
                    color: Colors.black54,
                    fontSize: 16,
                  ),
                ),
                DropdownButton<CartonSize>(
                  isDense: true,
                  value: selectedCatonSize,
                  style: TextStyle(color: Colors.black, fontSize: 14),
                  underline: Container(
                    height: 1,
                    color: Colors.grey,
                  ),
                  onChanged: (CartonSize? newValue) {
                    setState(() {
                      if (newValue!.name == MANAGE_CARTONSIZE) {
                        selectedCatonSize = null;
                        _manageCartonSize();
                        return;
                      }
                      selectedCatonSize = newValue;
                      _widthController.text =
                          selectedCatonSize!.width.toString();
                      _heightController.text =
                          selectedCatonSize!.height.toString();
                      _lengthController.text =
                          selectedCatonSize!.length.toString();
                    });
                  },
                  isExpanded: true,
                  items: _cartonSizes
                      .map<DropdownMenuItem<CartonSize>>((CartonSize value) {
                    return DropdownMenuItem<CartonSize>(
                      value: value,
                      child: Text(value.name ?? "",
                          overflow: TextOverflow.ellipsis,
                          style: TextStyle(
                              color: value.name == MANAGE_CARTONSIZE
                                  ? secondaryColor
                                  : primaryColor)),
                    );
                  }).toList(),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  _manageCartonSize() {
    Navigator.push<Package>(
      context,
      CupertinoPageRoute(builder: (context) => CartonSizeList()),
    );
  }

  _removeCargo(CargoType cargo) {
    setState(() {
      _cargoTypes.remove(cargo);
    });
  }

  _updateCargo(CargoType cargo) {
    setState(() {
      var _c = _cargoTypes.firstWhere((e) => e.id == cargo.id);
      if (_c != null) {
        _c.weight = cargo.weight;
        _c.qty = cargo.qty;
      }
    });
  }

  _addCarton() async {
    bool isFromPackages = _selectedCartonType == carton_from_packages;
    bool isFromCartons = _selectedCartonType == carton_from_cartons;

    if (_fcsShipment == null && _isNew) {
      showMsgDialog(context, "Error", "Please select FCS shipment");
      return;
    }

    if (_user == null && isFromPackages) {
      showMsgDialog(context, "Error", "Please select FCS ID");
      return;
    }

    if (consignee == null && isFromCartons) {
      showMsgDialog(context, "Error", "Please select consignee's FCS ID");
      return;
    }

    if (sender == null && isFromCartons) {
      showMsgDialog(context, "Error", "Please select sender's FCS ID");
      return;
    }

    double l = double.parse(_lengthController.text, (s) => 0);
    double w = double.parse(_widthController.text, (s) => 0);
    double h = double.parse(_heightController.text, (s) => 0);

    Carton carton = Carton();
    carton.id = _carton!.id;
    carton.cartonType = _selectedCartonType!;
    carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
    if (isFromPackages) {
      carton.userID = _user?.id ?? '';
      carton.fcsID = _user?.fcsID ?? '';
      carton.userName = _user?.name ?? '';
      carton.packages = _carton!.packages.where((e) => e.isChecked).toList();
    }

    if (isFromCartons) {
      carton.userID = consignee?.id ?? "";
      carton.fcsID = consignee?.fcsID ?? "";
      carton.userName = consignee?.name ?? "";
      carton.senderID = sender?.id ?? "";
      carton.senderFCSID = sender?.fcsID ?? "";
      carton.senderName = sender?.name ?? "";
    }

    carton.cargoTypes = _carton!.cargoTypes;
    carton.length = l;
    carton.width = w;
    carton.height = h;
    carton.deliveryAddress = _carton!.deliveryAddress;

    try {
      Carton _c = await Navigator.push(
        context,
        CupertinoPageRoute(
            builder: (context) => PackageCartonEditor(
                  carton: carton,
                  isNew: _isNew,
                  consignee: _user,
                )),
      );
      if (_c == null) return;
      var cartonModel = Provider.of<CartonModel>(context, listen: false);
      Carton _carton = await cartonModel.getCarton(_c.id ?? "");
      if (isFromPackages) {
        _cartons.add(_carton);
      }

      if (isFromCartons) {
        _cartonsFromCartons.add(_carton);
      }

      setState(() {});
    } catch (e) {
      showMsgDialog(context, "Error", e.toString());
    }
  }

  _addMixCarton(Carton carton) {
    if (carton == null) return;
    if (this._mixCartons.any((c) => c.id == carton.id)) return;
    setState(() {
      this._mixCartons.add(carton);
    });
  }

  _removeMixCarton(Carton carton) {
    setState(() {
      this._mixCartons.removeWhere((c) => c.id == carton.id);
    });
  }

  _creatMixCarton() async {
    if (_fcsShipment == null && _isNew) {
      showMsgDialog(context, "Error", "Please select FCS shipment");
      return;
    }
    if (this._mixCartons.length == 0) {
      showMsgDialog(context, "Error", "Expect at least one carton");
      return;
    }
    Carton carton = Carton();
    carton.id = _carton!.id;
    carton.cartonType = _selectedCartonType!;
    carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
    carton.mixBoxType = _selectedMixBoxType!;
    carton.mixCartons = this._mixCartons;
    setState(() {
      _isLoading = true;
    });
    try {
      CartonModel cartonModel =
          Provider.of<CartonModel>(context, listen: false);
      if (_isNew) {
        await cartonModel.createCarton(carton);
      } else {
        await cartonModel.updateCarton(carton);
      }
      Navigator.pop(context, true);
    } catch (e) {
      showMsgDialog(context, "Error", e.toString());
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  _save() async {
    bool isFromPackages = _selectedCartonType == carton_from_packages;
    bool isFromCartons = _selectedCartonType == carton_from_cartons;
    if (_cargoTypes.length == 0 && (isFromPackages || isFromCartons)) {
      showMsgDialog(context, "Error", "Expect at least one cargo type");
      return;
    }
    if (_cargoTypes.where((c) => c.weight <= 0).isNotEmpty) {
      showMsgDialog(context, "Error", "Invalid cargo weight");
      return;
    }
    double l = double.parse(_lengthController.text);
    double w = double.parse(_widthController.text);
    double h = double.parse(_heightController.text);
    if ((l <= 0 || w <= 0 || h <= 0) && (isFromPackages || isFromCartons)) {
      showMsgDialog(context, "Error", "Invalid dimension");
      return;
    }
    if (_deliveryAddress == null && (isFromPackages || isFromCartons)) {
      showMsgDialog(context, "Error", "Invalid delivery address");
      return;
    }

    Carton carton = Carton();
    carton.id = _carton!.id;
    carton.cartonType = _selectedCartonType!;
    carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
    if (isFromPackages) {
      carton.userID = _user?.id ?? "";
      carton.packages = _carton!.packages.where((e) => e.isChecked).toList();
    }
    if (isFromCartons) {
      carton.userID = consignee?.id ?? "";
      carton.senderID = sender?.id ?? "";
    }

    carton.cargoTypes = _cargoTypes;
    carton.length = l;
    carton.width = w;
    carton.height = h;
    carton.deliveryAddress = _deliveryAddress;

    setState(() {
      _isLoading = true;
    });
    try {
      CartonModel cartonModel =
          Provider.of<CartonModel>(context, listen: false);
      await cartonModel.updateCarton(carton);
      Navigator.pop(context, true);
    } catch (e) {
      showMsgDialog(context, "Error", e.toString());
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }
}
