import 'dart:collection';

import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/customer_property.dart';
import 'package:aitrainer_app/model/product_test.dart';
import 'package:aitrainer_app/model/purchase.dart';
import 'package:aitrainer_app/repository/property_repository.dart';
import 'package:aitrainer_app/service/customer_service.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/product_test_service.dart';
import 'package:aitrainer_app/service/purchase.dart';
import 'package:aitrainer_app/util/not_found_exception.dart';

class GenderItem {
  GenderItem(this.dbValue, this.name);
  final String dbValue;
  String name;
}

class CustomerRepository with Logging {
  Customer customer;
  Customer _trainee;
  List<Customer> _trainees;
  List<CustomerProperty> _allProperties;
  final PropertyRepository propertyRepository = PropertyRepository();

  //List<CustomerRepository> customerList = List<CustomerRepository>();
  bool visibleDetails = false;
  List<GenderItem> genders;

  CustomerRepository({this.customer}) {
    customer = Customer();
    genders = [
      GenderItem("m", "Man"),
      GenderItem("w", "Woman"),
    ];
  }

  String getGenderByName(String name) {
    String dbValue;
    genders.forEach((element) {
      if (element.name == name) {
        dbValue = element.dbValue;
      }
    });
    return dbValue;
  }

  String getGenderByDBValue(String dbValue) {
    String name;
    genders.forEach((element) {
      if (element.dbValue == dbValue) {
        name = element.name;
      }
    });
    return name;
  }

  String get name {
    return this.customer.name != null ? this.customer.name : "";
  }

  String get firstName {
    return this.customer.firstname != null ? this.customer.firstname : "";
  }

  String get sex {
    return this.customer.sex == "m" ? "Man" : "Woman";
  }

  int get birthYear {
    return this.customer.birthYear;
  }

  String get goal {
    return this.customer.goal;
  }

  String get fitnessLevel {
    return this.customer.fitnessLevel;
  }

  String get bodyType {
    return this.customer.bodyType;
  }

  setName(String name) {
    this.customer.name = name;
  }

  setFirstName(String firstName) {
    this.customer.firstname = firstName;
  }

  setPassword(String password) {
    this.customer.password = password;
  }

  setEmail(String email) {
    this.customer.email = email;
  }

  setSex(String sex) {
    this.customer.sex = sex;
  }

  setWeight(int weight) {
    final propertyName = "Weight";
    this.setCustomerProperty(propertyName, weight.toDouble());
  }

  setHeight(int height) {
    final propertyName = "Height";
    this.setCustomerProperty(propertyName, height.toDouble());
  }

  setCustomerProperty(String propertyName, double value) {
    if (this.customer.properties[propertyName] == null) {
      this.customer.properties[propertyName] = CustomerProperty(
          propertyId: propertyRepository.getPropertyByName("Height").propertyId,
          customerId: this.customer.customerId,
          propertyValue: value);
    } else {
      this.customer.properties[propertyName].propertyValue = value;
    }
    this.customer.properties[propertyName].dateAdd = DateTime.now();
    this.customer.properties[propertyName].newData = true;
  }

  double getWeight() {
    return getCustomerPropertyValue("Weight");
  }

  double getHeight() {
    return getCustomerPropertyValue("Height");
  }

  double getCustomerPropertyValue(String propertyName) {
    if (this.customer.properties[propertyName] == null) {
      return 0.0;
    } else {
      return this.customer.properties[propertyName].propertyValue;
    }
  }

  CustomerProperty getCustomerProperty(String propertyName) {
    return this.customer.properties[propertyName];
  }

  setBirthYear(int birthYear) {
    this.customer.birthYear = birthYear;
  }

  setFitnessLevel(String level) {
    this.customer.fitnessLevel = level;
  }

  setGoal(String goal) {
    this.customer.goal = goal;
  }

  setBodyType(String bodyType) {
    this.customer.bodyType = bodyType;
  }

  createNew() {
    this.customer = Customer();
  }

  Customer getCustomer() {
    return this.customer;
  }

  void setCustomer(Customer customer) {
    this.customer = customer;
  }

  Future<void> addCustomer() async {
    final Customer modelCustomer = customer;
    await CustomerApi().addCustomer(modelCustomer);
  }

  Future<void> saveCustomer() async {
    final Customer modelCustomer = customer;
    await CustomerApi().saveCustomer(modelCustomer);
    await this.saveProperties(modelCustomer.properties);
  }

  Future<void> saveProperties(LinkedHashMap<String, CustomerProperty> properties) async {
    properties.forEach((propertyName, property) async {
      if (property.newData == true) {
        await CustomerApi().addProperty(property);
        property.newData = false;
      }
    });
  }

  Future<Customer> getTraineeAsCustomer() async {
    this._trainee = await CustomerApi().getTrainee(Cache().userLoggedIn.customerId);
    return _trainee;
  }

  Future<List<Customer>> getTrainees() async {
    int trainerId = Cache().userLoggedIn.customerId;
    final results = await CustomerApi().getTrainees(trainerId);
    this._trainees = results;
    return results;
  }

  Future<List<CustomerProperty>> getAllCustomerProperties() async {
    int customerId = Cache().userLoggedIn.customerId;
    final results = await CustomerApi().getAllProperties(customerId);
    this._allProperties = results;
    return results;
  }

  List<CustomerProperty> getAllProperties() {
    return this._allProperties;
  }

  List<Customer> getTraineesList() {
    return _trainees;
  }

  void setTrainee(int traineeId) {
    if (_trainees == null) {
      return;
    }
    _trainees.forEach((element) {
      if (traineeId == element.customerId) {
        this._trainee = element;
      }
    });
  }

  void emptyTrainees() {
    _trainees = null;
    _trainee = null;
  }

  Customer getTrainee() {
    return this._trainee;
  }

  Customer getTraineeById(int customerId) {
    if (_trainees == null) {
      return null;
    }
    _trainees.forEach((element) {
      if (customerId == element.customerId) {
        this._trainee = element;
      }
    });
    return _trainee;
  }

  Future<List<Purchase>> getPurchase() async {
    int customerId = Cache().userLoggedIn.customerId;
    List<Purchase> purchases = await PurchaseApi().getPurchasesByCustomer(customerId);
    return purchases;
  }

  Future<void> addPurchase(Purchase purchase) async {
    await PurchaseApi().savePurchase(purchase);
  }

  Future<List<ProductTest>> getProductTests() async {
    List<ProductTest> tests = List();
    try {
      int customerId = Cache().userLoggedIn.customerId;
      tests = await ProductTestApi().getProductTestByCustomer(customerId);
    } on NotFoundException catch (ex) {
      log("Product Tests not found");
      Cache().productTests = tests;
    } on Exception catch (ex) {
      log(ex.toString());
      Cache().productTests = tests;
    }
    return tests;
  }

  Future<void> addProductTest(ProductTest productTest) async {
    await ProductTestApi().saveProductTest(productTest);
  }
}