package com.etroya.poligon.domain;

import com.etroya.poligon.domain.data.Drink;
import com.etroya.poligon.domain.data.Food;
import com.etroya.poligon.domain.data.Product;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;

public class ProductFactory {


    //    private ProductAbstract product;
//    private Review[] reviews = new Review[5];
    private Map<ProductAbstract, List<Review>> products = new HashMap<>();
    private static Map<String, ResourceFormatter> formatters
            = Map.of("en-GB", new ResourceFormatter(Locale.UK),
            "en-US", new ResourceFormatter(Locale.US),
            "zh-CN", new ResourceFormatter(Locale.CHINA));
    private ResourceFormatter formatter;


    public ProductFactory(Locale locale) {
        this(locale.toLanguageTag());
    }

    public ProductFactory(String languageTag) {
        changeLocale(languageTag);
    }

    public void changeLocale(String languageTag) {
        formatter = formatters.getOrDefault(languageTag, formatters.get("en-GB"));
    }

    public static Set<String> getSupportedLocales() {
        return formatters.keySet();
    }

    public ProductAbstract createProduct(int id, String name, BigDecimal price, Rating rating, LocalDate bestBefore) {
        ProductAbstract product = new Food(id, name, price, rating, bestBefore);
        products.putIfAbsent(product, new ArrayList<>());
        return product;
    }

    public ProductAbstract createProduct(int id, String name, BigDecimal price, Rating rating) {
        ProductAbstract product = new Drink(id, name, price, rating);
        products.putIfAbsent(product, new ArrayList<>());
        return product;
    }

    public ProductAbstract reviewProduct(ProductAbstract product, Rating rating, String comments) {
        List<Review> reviews = products.get(product);
        products.remove(product, reviews);
        reviews.add(new Review(rating, comments));
        int sum = 0;
        for (Review review : reviews) {
            sum += review.getRating().ordinal();
        }

        product = product.applyRating(Rateable.convert(Math.round((float) sum / reviews.size())));
        products.put(product, reviews);
        return product;
    }

    public void printProductReport(int id) {
        printProductReport(findProduct(id));
    }

    public void printProductReport(Comparator<ProductAbstract> sorter){
        List<ProductAbstract> productList = new ArrayList<>(products.keySet());
        productList.sort(sorter);
        StringBuilder txt = new StringBuilder();
        for(ProductAbstract product : productList){
            txt.append(formatter.formatProduct(product));
            txt.append('\n');
        }
        System.out.println(txt);
    }

    public void printProductReport(ProductAbstract product) {
        List<Review> reviews = products.get(product);
        StringBuilder txt = new StringBuilder();
        txt.append(formatter.formatProduct(product));
        txt.append('\n');
        Collections.sort(reviews);
        for (Review review : reviews) {
            txt.append(formatter.formatProduct(product));
            txt.append("\n");

        }
        if (reviews.isEmpty()) {
            txt.append(formatter.getText("no.reviews"));
            txt.append('\n');
        }
        System.out.println(txt);
    }

    public ProductAbstract findProduct(int id) {
        ProductAbstract result = null;
        for (ProductAbstract product : products.keySet()) {
            if (product.getId() == id) {
                result = product;
                break;
            }
        }
        return result;


    }

    private static class ResourceFormatter {
        private Locale locale;
        private ResourceBundle resources;
        private DateTimeFormatter dateFormat;
        private NumberFormat moneyFormat;

        private ResourceFormatter(Locale locale) {
            this.locale = locale;
            resources = ResourceBundle.getBundle("com.etroya.poligon", locale);
            dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
                    .localizedBy(locale);
            moneyFormat = NumberFormat.getCurrencyInstance(locale);
        }

        private String formatProduct(ProductAbstract product) {
            return MessageFormat.format(resources.getString("product"),
                    product.getName(),
                    moneyFormat.format(product.getPrice()),
                    product.getRating().getStars(),
                    dateFormat.format(product.getBestBefore()));
        }

        private String formatReview(Review review) {
            return MessageFormat.format(resources.getString("review"),
                    review.getRating().getStars(),
                    review.getComments());
        }

        private String getText(String key) {
            return resources.getString(key);
        }

    }


//    public static Product createProduct(ProductType productType) {
//        switch (productType) {
//            case FOOD:
//                return new Food();
//            case DRINK:
//                return new Drink();
//
//        }
//        return null;
//
//    }
}

@@ -121,55 +121,8 @@
 ood;
-%0Aimport com.etroya.poligon.domain.data.Product;
 %0A%0Aim
@@ -375,100 +375,8 @@
  %7B%0A%0A
-%0A    //    private ProductAbstract product;%0A//    private Review%5B%5D reviews = new Review%5B5%5D;%0A
     
@@ -2395,16 +2395,17 @@
  sorter)
+ 
 %7B%0A      
@@ -2572,16 +2572,17 @@
      for
+ 
 (Product
@@ -2612,16 +2612,17 @@
 uctList)
+ 
 %7B%0A      
@@ -3403,77 +3403,14 @@
     
-ProductAbstract result = null;%0A        for (ProductAbstract product :
+return
  pro
@@ -3423,20 +3423,20 @@
 keySet()
-) %7B%0A
+%0A   
         
@@ -3443,107 +3443,93 @@
     
-if (product.getId() == id) %7B%0A                result = product;%0A                break;%0A            %7D
+ .stream()%0A                .filter(p -%3E p.getId() == id)%0A                .findFirst()
 %0A   
@@ -3533,26 +3533,24 @@
         
-%7D%0A
         
 return r
@@ -3545,24 +3545,31 @@
     
-return result;%0A%0A
+.orElseGet(() -%3E null);
 %0A   

rewrite findProduct method