public class DetailAdapter extends RecyclerView.Adapter<DetailAdapter.DetailHolder> {

    private final ArrayList<Menu> menus;
    private final ArrayList<Dish> dishes;
    private final Context context;
    private final RestaurantService restaurantService;

    public DetailAdapter(ArrayList<Dish> dishes, ArrayList<Menu> menus, Context context) {
        this.dishes = dishes;
        this.menus = menus;
        this.context = context;
        this.restaurantService = ServiceFactory.getRestaurantService(context);
        notifyDataSetChanged();
    }

    @Override
    public DetailHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.dishes_menus_item, parent, false);
        return new DetailHolder(view);
    }

    @Override
    public void onBindViewHolder(final DetailHolder holder, final int position) {
        if (this.dishes != null) {
            Dish current = this.dishes.get(position);
            holder.name.setText(current.getName());
            holder.description.setText(current.getDescription());
            holder.price.setText(String.valueOf(current.getPrice() + " €"));
        } else if (this.menus != null) {
            Menu current = this.menus.get(position);
            holder.name.setText(current.getName());
            holder.description.setText(current.getDescription());
            holder.price.setText(String.valueOf(current.getPrice() + " €"));
        }

        holder.view.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                LayoutInflater inflater = LayoutInflater.from(context);
                final LinearLayout extra = (LinearLayout) inflater.inflate(context.getResources().getLayout(R.layout.extra_information), null);
                TextView nameDish = (TextView) extra.findViewById(R.id.name_refill);
                TextView descriptionDish = (TextView) extra.findViewById(R.id.description_refill);
                TextView orderedToday = (TextView) extra.findViewById(R.id.ordered_today_refill);
                TextView orderedWeek = (TextView) extra.findViewById(R.id.ordered_week_refill);
                TextView orderedMonth = (TextView) extra.findViewById(R.id.ordered_month_refill);
                TextView priceDish = (TextView) extra.findViewById(R.id.price_refill);
                TextView averagePunctuation = (TextView) extra.findViewById(R.id.average_punctuation_refill);

                String id = "";
                if (dishes != null) id = dishes.get(position).getId();
                else if (menus != null) id = menus.get(position).getId();

                nameDish.setText(holder.name.getText().toString());
                descriptionDish.setText(holder.description.getText().toString());
                orderedToday.setText(String.format("%s times", String.valueOf(restaurantService.getTimesOrdered(id, Calendar.DATE))));
                orderedWeek.setText(String.format("%s times", String.valueOf(restaurantService.getTimesOrdered(id, Calendar.WEEK_OF_YEAR))));
                orderedMonth.setText(String.format("%s times", String.valueOf(restaurantService.getTimesOrdered(id, Calendar.MONTH))));
                priceDish.setText(holder.price.getText().toString());
                averagePunctuation.setText(restaurantService.getAveragePunctuationOfDish(id) == -1.0 ?
                        "---" :
                        Utils.toStringWithTwoDecimals(restaurantService.getAveragePunctuationOfDish(id)) + " / 5.0");

                final String finalId = id;
                AlertDialog alertDialog = new AlertDialog.Builder(context)
                        .setTitle(context.getResources().getString(R.string.extra_information))
                        .setView(extra)
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                // do nothing
                            }
                        })
                        .setNegativeButton(R.string.reviews, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent intent = new Intent(context, ReviewListActivity.class);
                                intent.putExtra(ReviewListActivity.DISH_ID, finalId);
                                context.startActivity(intent);
                            }
                        })
                        .setOnCancelListener(new DialogInterface.OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                // do nothing
                            }
                        })
                        .create();
                alertDialog.setCanceledOnTouchOutside(false);
                alertDialog.show();
                return true;
            }
        });
    }

    @Override
    public int getItemCount() {
        if (dishes != null) {
            return dishes.size();
        } else if (menus != null) {
            return menus.size();
        }
        return 0;
    }

    class DetailHolder extends RecyclerView.ViewHolder {

        public View view;
        TextView name;
        TextView description;
        TextView price;

        DetailHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.name = (TextView) itemView.findViewById(R.id.name);
            this.description = (TextView) itemView.findViewById(R.id.description);
            this.price = (TextView) itemView.findViewById(R.id.price);
        }
    }
} @Getter
@Setter
@AllArgsConstructor(suppressConstructorProperties = true)
@NoArgsConstructor
@ToString
@Builder
public class Dish implements Entity {

    private String id;
    private String name;
    private Double price;
    private String description;

    private Map<String, Object> reviews = new LinkedHashMap<>();


    @Override
    public String getId() {
        return id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

} @Getter
@Setter
@AllArgsConstructor(suppressConstructorProperties = true)
@NoArgsConstructor
@ToString
@Builder
public class Menu implements Entity {

    private String id;
    private String name;
    private Double price;
    private String description;

    private Map<String, Object> mainDishes = new LinkedHashMap<>();
    private Map<String, Object> secondaryDishes = new LinkedHashMap<>();
    private Map<String, Object> otherDishes = new LinkedHashMap<>();
    private Map<String, Object> reviews = new LinkedHashMap<>();

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

} @Getter
@Setter
@AllArgsConstructor(suppressConstructorProperties = true)
@NoArgsConstructor
@ToString
@Builder
public class OpenTime implements Entity {

    private String id;
    private Date startDate;
    private Date endDate;

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

} @Getter
@Setter
@AllArgsConstructor(suppressConstructorProperties = true)
@NoArgsConstructor
@ToString
@Builder
public class Restaurant implements Entity {

    private String id;
    private String name;
    private String location;
    private Integer phone;
    private String description;
    private String website;
    private Integer numberOfTables;

    private Map<String, Object> openTimes = new LinkedHashMap<>();
    private Map<String, Object> menus = new LinkedHashMap<>();
    private Map<String, Object> dishes = new LinkedHashMap<>();
    private Map<String, Object> users = new LinkedHashMap<>();
    private Map<String, Object> externalOrders = new LinkedHashMap<>();
    private Map<String, Object> reviews = new LinkedHashMap<>();

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

} public class RestaurantService extends Service<Restaurant> {

    private final Repository<Menu> menuRepository;
    private final Repository<Dish> dishRepository;
    @SuppressWarnings({"unused", "FieldCanBeLocal"})
    private final Repository<Image> imageRepository;
    private final Repository<OpenTime> openTimeRepository;
    private final Repository<Order> orderRepository;
    private final Repository<OrderItem> orderItemRepository;
    private final Repository<User> userRepository;
    private final Repository<Review> reviewRepository;

    public RestaurantService(Repository<Restaurant> repository,
                             Repository<Menu> menuRepository,
                             Repository<Dish> dishRepository,
                             Repository<Image> imageRepository,
                             Repository<OpenTime> openTimeRepository,
                             Repository<Order> orderRepository,
                             Repository<OrderItem> orderItemRepository,
                             Repository<User> userRepository,
                             Repository<Review> reviewRepository) {
        super(repository);
        this.menuRepository = menuRepository;
        this.dishRepository = dishRepository;
        this.imageRepository = imageRepository;
        this.openTimeRepository = openTimeRepository;
        this.orderRepository = orderRepository;
        this.orderItemRepository = orderItemRepository;
        this.userRepository = userRepository;
        this.reviewRepository = reviewRepository;
    }

    public void addOpenTimes(Restaurant restaurant, List<OpenTime> openTimeList) {
        Map<String, Object> openTimeMap = new LinkedHashMap<>();
        for (OpenTime time : openTimeList) {
            String insertedId = openTimeRepository.insert(time).getId();
            openTimeMap.put(insertedId, true);
        }
        restaurant.setOpenTimes(openTimeMap);
    }

    public void removeOpenTimes(String restaurantId) {
        Restaurant restaurant = repository.get(restaurantId);
        if (restaurant == null || restaurant.getOpenTimes() == null || restaurant.getOpenTimes().isEmpty()) return;
        for (String id : restaurant.getOpenTimes().keySet()) {
            openTimeRepository.delete(id);
        }
    }

    public void addDishesAndMenus(Restaurant restaurant, ArrayList<Dish> dishes, ArrayList<Menu> menus) {
        Map<String, Object> dishesMap = new LinkedHashMap<>();
        for (Dish dish : dishes) {
            String insertedId = dishRepository.insert(dish).getId();
            dishesMap.put(insertedId, true);
        }
        restaurant.setDishes(dishesMap);

        Map<String, Object> menusMap = new LinkedHashMap<>();
        for (Menu menu : menus) {
            String insertedId = menuRepository.insert(menu).getId();
            menusMap.put(insertedId, true);
        }
        restaurant.setMenus(menusMap);

        String newId = repository.insert(restaurant).getId();
        addUserToRestaurant(newId, Preferences.getCurrentUserEmail());
    }

    public ArrayList<Dish> getDishes(String restaurantId) {
        ArrayList<Dish> dishes = new ArrayList<>();
        Restaurant restaurant = repository.get(restaurantId);
        if (restaurant != null) {
            for (String dishId : restaurant.getDishes().keySet()) {
                dishes.add(dishRepository.get(dishId));
            }
        }
        return dishes;
    }

    public ArrayList<Menu> getMenus(String restaurantId) {
        ArrayList<Menu> menus = new ArrayList<>();
        Restaurant restaurant = repository.get(restaurantId);
        if (restaurant != null) {
            for (String menuId : restaurant.getMenus().keySet()) {
                menus.add(menuRepository.get(menuId));
            }
        }
        return menus;
    }

    public List<OpenTime> getOpenTimes(Restaurant restaurant) {
        List<OpenTime> result = new ArrayList<>();
        for (String key : restaurant.getOpenTimes().keySet()) {
            result.add(openTimeRepository.get(key));
        }
        return result;
    }

    public void addUserToRestaurant(String restaurantId, String userId) {
        Restaurant restaurant = repository.get(restaurantId);
        Map<String, Object> users = restaurant.getUsers();
        if (users == null) {
            users = new LinkedHashMap<>();
        }
        users.put(userId, true);
        restaurant.setUsers(users);
        repository.update(restaurant);

        User user = userRepository.get(userId);
        Map<String, Object> restaurants = user.getMyRestaurants();
        if (restaurants == null) {
            restaurants = new LinkedHashMap<>();
        }
        restaurants.put(restaurantId, true);
        user.setMyRestaurants(restaurants);
        userRepository.update(user);
    }

    public Integer getDaysOpen(Restaurant current) {
        return current.getOpenTimes().size();
    }

    public Integer getDishesCount(Restaurant current) {
        return current.getDishes().size();
    }

    public Integer getMenusCount(Restaurant current) {
        return current.getMenus().size();
    }

    public boolean isPartOfTheStuff(String restaurantId, String user) {
        Restaurant restaurant = repository.get(restaurantId);
        for (String userKey : restaurant.getUsers().keySet()) {
            if (userKey.equals(user)) return true;
        }
        return false;
    }

    private List<String> getOrders(String restaurantId) {
        Restaurant restaurant = repository.get(restaurantId);
        List<String> ordersList = new ArrayList<>();

        User user;
        for (String userKey : restaurant.getUsers().keySet()) {
            user = userRepository.get(userKey);
            if (user != null && user.getMyOrders() != null) {
                for (String key : user.getMyOrders().keySet()) {
                    if (!isExternal(key)) ordersList.add(key);
                }
            }
        }

        if (restaurant.getExternalOrders() != null) {
            ordersList.addAll(restaurant.getExternalOrders().keySet());
        }

        return ordersList;
    }

    private boolean isExternal(String orderKey) {
        for (Restaurant restaurant : repository.all()) {
            if (restaurant.getExternalOrders() != null && restaurant.getExternalOrders().containsKey(orderKey))
                return true;
        }
        return false;
    }

    private boolean checkTime(Date date, int kind) {
        Calendar currentCalendar = Calendar.getInstance();
        currentCalendar.setTime(Utils.getAnalyticsDate());

        Calendar orderCalendar = Calendar.getInstance();
        orderCalendar.setTime(date);
        switch (kind) {
            case Calendar.DATE:
                if (orderCalendar.get(Calendar.YEAR) == currentCalendar.get(Calendar.YEAR) &&
                        orderCalendar.get(Calendar.MONTH) == currentCalendar.get(Calendar.MONTH) &&
                        orderCalendar.get(Calendar.DATE) == currentCalendar.get(Calendar.DAY_OF_MONTH)) {
                    return true;
                }
                break;
            case Calendar.WEEK_OF_YEAR:
                if (orderCalendar.get(Calendar.YEAR) == currentCalendar.get(Calendar.YEAR) &&
                        orderCalendar.get(Calendar.WEEK_OF_YEAR) == currentCalendar.get(Calendar.WEEK_OF_YEAR)) {
                    return true;
                }
                break;
            case Calendar.MONTH:
                if (orderCalendar.get(Calendar.YEAR) == currentCalendar.get(Calendar.YEAR) &&
                        orderCalendar.get(Calendar.MONTH) == currentCalendar.get(Calendar.MONTH)) {
                    return true;
                }
                break;
            default:
                return false;
        }
        return false;
    }

    private Integer getNumberOptions(Menu menu) {
        return  (!menu.getMainDishes().isEmpty() ? 1 : 0) +
                (!menu.getSecondaryDishes().isEmpty() ? 1 : 0) +
                (!menu.getOtherDishes().isEmpty() ? 1 : 0);
    }

    private double getPriceOfOrder(String id) {
        Order order = orderRepository.get(id);
        if (order == null) return 0.0;

        Map<String, List<String>> menuMap = new LinkedHashMap<>();

        double total = 0.0;
        for (String orderItemId : order.getOrderItems().keySet()) {
            OrderItem orderItem = orderItemRepository.get(orderItemId);
            if (orderItem != null) {
                if (orderItem.getMenuId() == null) {
                    total += dishRepository.get(orderItem.getDishId()).getPrice();
                } else {
                    List<String> dishes = menuMap.get(orderItem.getMenuId());
                    if (dishes == null) {
                        dishes = new ArrayList<>();
                    }
                    dishes.add(orderItem.getDishId());
                    menuMap.put(orderItem.getMenuId(), dishes);
                }
            }
        }
        Menu menu;
        for (String key : menuMap.keySet()) {
            menu = menuRepository.get(key);
            Integer numberOptions = getNumberOptions(menu);
            double totalMenus = (double) (menuMap.get(key).size() / numberOptions);
            total += totalMenus*menu.getPrice();
        }

        return total;
    }

    private Map<String, Integer> getDishesCountMap(String restaurantId, int kind) {
        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return new HashMap<>();

        Map<String, Integer> map = new HashMap<>();
        for (Dish dish : getDishes(restaurantId)) {
            map.put(dish.getId(), 0);
        }

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (order.getOrderItems() == null || !checkTime(order.getDate(), kind)) continue;

            OrderItem orderItem;
            for (String orderItemKey : order.getOrderItems().keySet()) {
                orderItem = orderItemRepository.get(orderItemKey);
                if (orderItem.getMenuId() == null) {
                    Integer count = map.get(orderItem.getDishId()) + 1;
                    map.put(orderItem.getDishId(), count);
                }
            }
        }

        return map;
    }

    private Map<String, Integer> getMenusCountMap(String restaurantId, int kind) {
        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return new HashMap<>();

        Map<String, Integer> map = new HashMap<>();
        for (Menu menu : getMenus(restaurantId)) {
            map.put(menu.getId(), 0);
        }

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (order.getOrderItems() == null || !checkTime(order.getDate(), kind)) continue;

            OrderItem orderItem;
            for (String orderItemKey : order.getOrderItems().keySet()) {
                orderItem = orderItemRepository.get(orderItemKey);
                if (orderItem.getMenuId() != null) {
                    Integer count = map.get(orderItem.getMenuId()) + 1;
                    map.put(orderItem.getMenuId(), count);
                }
            }
        }

        return map;
    }

    private double getPaidOfOrder(String id) {
        Order order = orderRepository.get(id);
        if (order == null) return 100.0;

        Map<String, List<Pair<String, Boolean>>> menuMap = new LinkedHashMap<>();
        double total = getPriceOfOrder(id);
        double paid = 0.0;

        for (String orderItemId : order.getOrderItems().keySet()) {
            OrderItem orderItem = orderItemRepository.get(orderItemId);
            if (orderItem != null) {
                if (orderItem.getMenuId() == null) {
                    if (orderItem.isPaid()) {
                        paid += dishRepository.get(orderItem.getDishId()).getPrice();
                    }
                } else {
                    List<Pair<String, Boolean>> dishes = menuMap.get(orderItem.getMenuId());
                    if (dishes == null) {
                        dishes = new ArrayList<>();
                    }
                    dishes.add(new Pair<>(orderItem.getDishId(), orderItem.isPaid()));
                    menuMap.put(orderItem.getMenuId(), dishes);
                }
            }
        }
        Menu menu;
        for (String key : menuMap.keySet()) {
            menu = menuRepository.get(key);

            Integer numberPaid = 0;
            for (Pair<String, Boolean> pair : menuMap.get(key)) {
                if (pair.second) ++numberPaid;
            }
            if (numberPaid != 0) {
                double totalPaid = (double) (numberPaid / menuMap.get(key).size());
                double totalMenus = (double) (menuMap.get(key).size() / getNumberOptions(menu));
                paid += totalPaid*totalMenus*menu.getPrice();
            }
        }

        return (paid/total)*100.0;
    }

    public Integer getOrdersCount(String restaurantId, int kind) {
        Integer count = 0;

        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return 0;

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind)) ++count;
        }
        return count;
    }

    public Double getAveragePrice(String restaurantId, int kind) {
        double total = 0.0;
        double count = 0.0;

        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return 0.0;

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind)) {
                total += getPriceOfOrder(orderKey);
                count += 1.0;
            }
        }
        return total/count;
    }

    public Double getTotalEarned(String restaurantId, int kind) {
        double total = 0.0;

        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return 0.0;

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind)) total += getPriceOfOrder(orderKey);
        }
        return total;
    }

    public String getBestDish(String restaurantId, int kind) {
        Map<String, Integer> map = getDishesCountMap(restaurantId, kind);

        String bestId = "";
        Integer max = -1;
        for (String key : map.keySet()) {
            Integer current = map.get(key);
            if (current > max) {
                max = current;
                bestId = key;
            }
        }

        if (bestId.isEmpty()) return "---";
        else return dishRepository.get(bestId).getName() + ": " + max + " times.";
    }

    public String getWorstDish(String restaurantId, int kind) {
        Map<String, Integer> map = getDishesCountMap(restaurantId, kind);

        String bestId = "";
        Integer min = Integer.MAX_VALUE;
        for (String key : map.keySet()) {
            Integer current = map.get(key);
            if (current < min) {
                min = current;
                bestId = key;
            }
        }

        if (bestId.isEmpty()) return "---";
        else return dishRepository.get(bestId).getName() + ": " + min + " times.";
    }

    public String getBestMenu(String restaurantId, int kind) {
        Map<String, Integer> map = getMenusCountMap(restaurantId, kind);

        String bestId = "";
        Integer max = -1;
        for (String key : map.keySet()) {
            Integer current = map.get(key)/getNumberOptions(menuRepository.get(key));
            if (current > max) {
                max = current;
                bestId = key;
            }
        }

        if (bestId.isEmpty()) return "---";
        else return menuRepository.get(bestId).getName() + ": " + max + " times.";
    }

    public String getWorstMenu(String restaurantId, int kind) {
        Map<String, Integer> map = getMenusCountMap(restaurantId, kind);

        String bestId = "";
        Integer min = Integer.MAX_VALUE;
        for (String key : map.keySet()) {
            Integer current = map.get(key)/getNumberOptions(menuRepository.get(key));
            if (current < min) {
                min = current;
                bestId = key;
            }
        }

        if (bestId.isEmpty()) return "---";
        else return menuRepository.get(bestId).getName() + ": " + min + " times.";
    }

    public String getBestTimeRange(String restaurantId, int kind) {
        Integer[] hours = new Integer[24];
        for (int i = 0; i < hours.length; i++) hours[i] = 0;

        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return "---";

        Calendar calendar = Calendar.getInstance();
        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind)) {
                calendar.setTime(order.getDate());
                ++hours[calendar.get(Calendar.HOUR_OF_DAY)];
            }
        }

        int max = 0;
        int index = -1;
        for (int i = 0; i < hours.length; i++) {
            if (hours[i] > max) {
                max = hours[i];
                index = i;
            }
        }

        if (index == -1) return "---";

        String result = "";
        if (index < 10) result += '0';
        result += String.valueOf(index) + "h - ";
        ++index;
        if (index < 10) result += '0';
        result += String.valueOf(index) + "h";
        return result;
    }

    public String getAverageTime(String restaurantId, int kind) {
        long total = 0;
        long count = 0;

        List<String> ordersList = getOrders(restaurantId);
        if (ordersList.isEmpty()) return "No finished orders";

        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind) && getPaidOfOrder(orderKey) == 100.0) {
                total += (order.getLastDate().getTime() - order.getDate().getTime());
                ++count;
            }
        }

        if (count == 0) return "No finished orders";

        long averageTime = total/count;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(averageTime);

        return  String.valueOf(calendar.get(Calendar.HOUR_OF_DAY)) + "h " +
                String.valueOf(calendar.get(Calendar.MINUTE) + "min");
    }

    public double getAveragePunctuationOfRestaurant(String restaurantId, int kind) {
        Restaurant restaurant = repository.get(restaurantId);
        double average = -1.0;
        double count = 0.0;
        double total = 0.0;
        if (restaurant.getReviews() != null && !restaurant.getReviews().isEmpty()) {
            Review review;
            for (String reviewKey : restaurant.getReviews().keySet()) {
                review = reviewRepository.get(reviewKey);
                if (review != null && review.getDate() != null && checkTime(review.getDate(), kind)) {
                    total += review.getPoints();
                    count += 1.0;
                }
            }
            if (count == 0.0) average = -1.0;
            else average = total / count;
        }
        return average;
    }

    public Integer getReviewsCount(String restaurantId, int kind) {
        Restaurant restaurant = repository.get(restaurantId);
        Integer count = 0;
        if (restaurant.getReviews() != null && !restaurant.getReviews().isEmpty()) {
            Review review;
            for (String reviewKey : restaurant.getReviews().keySet()) {
                review = reviewRepository.get(reviewKey);
                if (review != null && review.getDate() != null && checkTime(review.getDate(), kind)) {
                    ++count;
                }
            }
        }
        return count;
    }

    public PieChartData getAllDishesCount(String restaurantId, int kind) {
        Map<String, Integer> map = getDishesCountMap(restaurantId, kind);

        Integer count = 0;
        for (Integer val : map.values()) {
            if (val != 0) ++count;
        }

        PieChartData data = new PieChartData(count);
        String[] xData = data.getXData();
        float[] yData = data.getYData();

        Float total = 0.0f;
        for (Integer value : map.values()) total += value;

        Integer i = 0;
        for (String key : map.keySet()) {
            if (map.get(key) != 0) {
                String name = dishRepository.get(key).getName();
                Float percent = (map.get(key) / total) * 100.0f;
                xData[i] = name;
                yData[i] = percent;
                i++;
            }
        }

        data.setXData(xData);
        data.setYData(yData);
        return data;
    }

    public PieChartData getAllMenusCount(String restaurantId, int kind) {
        Map<String, Integer> map = getMenusCountMap(restaurantId, kind);

        Integer count = 0;
        for (Integer val : map.values()) {
            if (val != 0) ++count;
        }

        Menu menu;
        for (String key : map.keySet()) {
            menu = menuRepository.get(key);
            Integer current = map.get(key)/getNumberOptions(menu);
            map.put(key, current);
        }

        PieChartData data = new PieChartData(count);
        String[] xData = data.getXData();
        float[] yData = data.getYData();

        Float total = 0.0f;
        for (Integer value : map.values()) total += value;

        Integer i = 0;
        for (String key : map.keySet()) {
            if (map.get(key) != 0) {
                String name = menuRepository.get(key).getName();
                Float percent = (map.get(key) / total) * 100.0f;
                xData[i] = name;
                yData[i] = percent;
                i++;
            }
        }

        data.setXData(xData);
        data.setYData(yData);
        return data;
    }

    public PieChartData getAllOrdersCount(String restaurantId, int kind) {
        float[] time;
        if (kind == Calendar.DATE) time = new float[24];
        else if (kind == Calendar.WEEK_OF_YEAR) time = new float[7];
        else time = new float[31];
        for (int i = 0; i < time.length; i++) time[i] = 0;

        List<String> ordersList = getOrders(restaurantId);

        Calendar calendar = Calendar.getInstance();
        Order order;
        for (String orderKey : ordersList) {
            order = orderRepository.get(orderKey);
            if (checkTime(order.getDate(), kind)) {
                calendar.setTime(order.getDate());
                if (kind == Calendar.DATE)
                    time[calendar.get(Calendar.HOUR_OF_DAY)] += 1.0f;
                else if (kind == Calendar.WEEK_OF_YEAR)
                    time[calendar.get(Calendar.DAY_OF_WEEK)-1] += 1.0f;
                else
                    time[calendar.get(Calendar.DAY_OF_MONTH)] += 1.0f;
            }
        }

        Integer count = 0;
        for (float t : time) if (t != 0) ++count;

        PieChartData data = new PieChartData(count);
        String[] xData = data.getXData();
        float[] yData = data.getYData();

        Integer j = 0;
        for (int i = 0; i < time.length; i++) {
            if (time[i] != 0) {
                yData[j] = time[i];


                String label = "";
                if (kind == Calendar.DATE) {
                    if (i < 10) label += '0';
                    label += String.valueOf(i) + "h - ";
                    if (i + 1 < 10) label += '0';
                    label += String.valueOf(i + 1) + 'h';
                } else if (kind == Calendar.WEEK_OF_YEAR) {
                    if (i == 0) label = "Sunday";
                    else if (i == 1) label = "Monday";
                    else if (i == 2) label = "Tuesday";
                    else if (i == 3) label = "Wednesday";
                    else if (i == 4) label = "Thursday";
                    else if (i == 5) label = "Friday";
                    else if (i == 6) label = "Saturday";
                } else {
                    label = "Day number " + String.valueOf(i) + " of the month.";
                }
                xData[j] = label;

                ++j;
            }
        }

        data.setXData(xData);
        data.setYData(yData);
        return data;
    }

    public boolean addNewUserToRestaurant(String restaurantId, String userToAdd) {
        Boolean found = false;
        for (User user : userRepository.all()) {
            if (user.getEmail().equals(userToAdd)) {
                found = true;
                break;
            }
        }
        if (!found) return false;

        for (Restaurant restaurant : repository.all()) {
            if (restaurant.getUsers() == null) continue;
            User user;
            for (String userKey : restaurant.getUsers().keySet()) {
                user = userRepository.get(userKey);
                if (user.getEmail().equals(userToAdd)) return false;
            }
        }

        addUserToRestaurant(restaurantId, Utils.skipAts(userToAdd));

        return true;
    }

    public int getTimesOrdered(String id, int kind) {
        int count = 0;

        Menu menu = menuRepository.get(id);

        for (Order order : orderRepository.all()) {
            if (order.getOrderItems() == null) continue;
            OrderItem orderItem;
            for (String orderItemKey : order.getOrderItems().keySet()) {
                orderItem = orderItemRepository.get(orderItemKey);
                if (checkTime(order.getDate(), kind)) {
                    if (menu != null && orderItem.getMenuId() != null && orderItem.getMenuId().equals(id)) ++count;
                    else if (menu == null && orderItem.getDishId().equals(id)) ++count;
                }
            }
        }

        if (menu != null) count /= getNumberOptions(menu);
        return count;
    }

    public double getAveragePunctuationOfRestaurant(String restaurantId) {
        Restaurant restaurant = repository.get(restaurantId);
        double average = -1.0;
        double count = 0.0;
        double total = 0.0;
        if (restaurant.getReviews() != null && !restaurant.getReviews().isEmpty()) {
            Review review;
            for (String reviewKey : restaurant.getReviews().keySet()) {
                review = reviewRepository.get(reviewKey);
                if (review != null) {
                    total += review.getPoints();
                    count += 1.0;
                }
            }
            average = total / count;
        }
        return average;
    }

    public double getAveragePunctuationOfDish(String id) {
        double average = -1.0;
        double count = 0.0;
        double total = 0.0;

        Object object;
        if (dishRepository.get(id) != null) object = dishRepository.get(id);
        else if (menuRepository.get(id) != null) object = menuRepository.get(id);
        else object = null;

        Map<String, Object> map;
        if (object != null) {
            if (object instanceof Dish) map = ((Dish) object).getReviews();
            else map = ((Menu) object).getReviews();

            if (map != null && !map.isEmpty()) {
                Review review;
                for (String reviewKey : map.keySet()) {
                    review = reviewRepository.get(reviewKey);
                    if (review != null) {
                        total += review.getPoints();
                        count += 1.0;
                    }
                }
                average = total / count;
            }
        }
        return average;
    }
} public final class ServiceFactory {

    private static DishService dishService;
    private static ImageService imageService;
    private static MenuService menuService;
    private static OpenTimeService openTimeService;
    private static OrderItemService orderItemService;
    private static OrderService orderService;
    private static RestaurantService restaurantService;
    private static ReviewService reviewService;
    private static UserService userService;

    public static DishService getDishService(Context context){
        if (dishService == null)
            dishService = new DishService(
                    new DishRepository(context));
        return dishService;
    }

    public static ImageService getImageService(Context context){
        if (imageService == null)
            imageService = new ImageService(
                    new ImageRepository(context));
        return imageService;
    }

    public static MenuService getMenuService(Context context){
        if (menuService == null)
            menuService = new MenuService(
                    new MenuRepository(context),
                    new DishRepository(context));
        return menuService;
    }

    public static OpenTimeService getOpenTimeService(Context context){
        if (openTimeService == null)
            openTimeService = new OpenTimeService(
                    new OpenTimeRepository(context));
        return openTimeService;
    }

    public static OrderItemService getOrderItemService(Context context){
        if (orderItemService == null)
            orderItemService = new OrderItemService(
                    new OrderItemRepository(context),
                    new DishRepository(context),
                    new MenuRepository(context));
        return orderItemService;
    }

    public static OrderService getOrderService(Context context){
        if (orderService == null)
            orderService = new OrderService(
                    new OrderRepository(context),
                    new OrderItemRepository(context),
                    new DishRepository(context),
                    new MenuRepository(context),
                    new RestaurantRepository(context),
                    new UserRepository(context));
        return orderService;
    }

    public static RestaurantService getRestaurantService(Context context){
        if (restaurantService == null)
            restaurantService = new RestaurantService(
                    new RestaurantRepository(context),
                    new MenuRepository(context),
                    new DishRepository(context),
                    new ImageRepository(context),
                    new OpenTimeRepository(context),
                    new OrderRepository(context),
                    new OrderItemRepository(context),
                    new UserRepository(context),
                    new ReviewRepository(context));
        return restaurantService;
    }

    public static ReviewService getReviewService(Context context) {
        if (reviewService == null) {
            reviewService = new ReviewService(
                    new ReviewRepository(context),
                    new RestaurantRepository(context),
                    new DishRepository(context),
                    new MenuRepository(context),
                    new UserRepository(context));
        }
        return reviewService;
    }

    public static UserService getUserService(Context context){
        if (userService == null)
            userService = new UserService(
                    new UserRepository(context),
                    new ImageRepository(context),
                    new RestaurantRepository(context),
                    new OrderRepository(context),
                    new OrderItemRepository(context));
        return userService;
    }

    public static Integer getServiceCount() {
        return 9;
    }
} public class UserService extends Service<User> {

    private final Repository<Image> imageRepository;
    private final Repository<Restaurant> restaurantRepository;
    private final Repository<Order> orderRepository;
    private final Repository<OrderItem> orderItemRepository;

    public UserService(Repository<User> repository,
                       Repository<Image> imageRepository,
                       Repository<Restaurant> restaurantRepository,
                       Repository<Order> orderRepository,
                       Repository<OrderItem> orderItemRepository) {
        super(repository);
        this.imageRepository = imageRepository;
        this.restaurantRepository = restaurantRepository;
        this.orderRepository = orderRepository;
        this.orderItemRepository = orderItemRepository;
    }

    public boolean logIn(GoogleSignInAccount acct) {
        String userId = Utils.skipAts(acct.getEmail());
        if (!repository.exists(userId)) {
            Uri imageUri = acct.getPhotoUrl();
            String imageId = null;
            if (imageUri != null) {
                Image image = Image.builder()
                        .imageFile(imageUri.toString()).description("Profile photo")
                        .build();
                imageId = imageRepository.insert(image).getId();
            }
            User user = User.builder()
                    .email(acct.getEmail())
                    .name(acct.getGivenName())
                    .lastName(acct.getFamilyName())
                    .location(null)
                    .imageId(imageId)
                    .build();
            user.setId(userId);
            repository.update(user);
        }
        Preferences.setCurrentUserEmail(userId);
        return true;
    }

    public String getProfilePhoto(String id) {
        Image image = imageRepository.get(repository.get(id).getImageId());
        if (image != null) return image.getImageFile();
        return null;
    }

    public String getUserName(String currentUser) {
        return repository.get(currentUser).getName();
    }

    public String getFirstRestaurantId(String currentUser) {
        User user = repository.get(currentUser);
        Map<String, Object> keys = user.getMyRestaurants();
        if (keys != null && !keys.keySet().isEmpty()) return (String) keys.keySet().toArray()[0];
        return null;
    }

    public String getFirstRestaurantName(String currentUser) {
        String restaurantId = null;
        User user = repository.get(currentUser);
        Map<String, Object> keys = user.getMyRestaurants();
        if (keys != null && !keys.keySet().isEmpty()) restaurantId = (String) keys.keySet().toArray()[0];
        if (restaurantId != null) return restaurantRepository.get(restaurantId).getName();
        return null;
    }

    public Integer getOrderCount(String currentUser) {
        User user = repository.get(currentUser);
        Map<String, Object> keys = user.getMyOrders();
        if (keys != null && !keys.keySet().isEmpty()) return keys.keySet().size();
        return null;
    }

    public boolean editUser(String id, String name, String lastName, String location) {
        User user = repository.get(id);
        user.setName(name);
        user.setLastName(lastName);
        user.setLocation(location);

        repository.update(user);
        return true;
    }

    public void editImage(String id, String uploadURL) {
        User user = repository.get(id);

        Image image = Image.builder().imageFile(uploadURL).build();
        String imageId = imageRepository.insert(image).getId();
        user.setImageId(imageId);

        repository.update(user);
    }

    public Order hasActiveOrder(String userKey) {
        User user = repository.get(userKey);

        Map<String, Object> dishesMap = new HashMap<>();
        Map<String, Object> menusMap = new HashMap<>();
        if (user != null && user.getMyRestaurants() != null) {
            Restaurant restaurant;
            for (String restaurantKey : user.getMyRestaurants().keySet()) {
                restaurant = restaurantRepository.get(restaurantKey);
                if (restaurant.getDishes() != null) dishesMap = restaurant.getDishes();
                if (restaurant.getMenus() != null) menusMap = restaurant.getMenus();
            }
        }

        if (user != null && user.getMyOrders() != null) {
            Order order;
            for (String orderKey : user.getMyOrders().keySet()) {
                order = orderRepository.get(orderKey);
                if (order != null && !isFinished(order.getOrderItems()) && !partOfYourRestaurant(order, dishesMap, menusMap))
                    return order;
            }
        }

        return null;
    }

    private boolean isFinished(Map<String, Object> orderItems) {
        if (orderItems != null) {
            OrderItem orderItem;
            for (String orderItemKey : orderItems.keySet()) {
                orderItem = orderItemRepository.get(orderItemKey);
                if (orderItem != null && !orderItem.isPaid()) return false;
            }
        }
        return true;
    }

    @SuppressWarnings("LoopStatementThatDoesntLoop")
    private boolean partOfYourRestaurant(Order order, Map<String, Object> dishesMap, Map<String, Object> menusMap) {
        OrderItem orderItem;
        for (String orderItemKey : order.getOrderItems().keySet()) {
            orderItem = orderItemRepository.get(orderItemKey);
            return orderItem.getMenuId() != null &&
                    menusMap.containsKey(orderItem.getMenuId()) ||
                    orderItem.getMenuId() == null && dishesMap.containsKey(orderItem.getDishId());
        }

        return false;
    }

    public List<Order> getOrdersToReview(String userKey) {
        List<Order> orders = new ArrayList<>();

        User user = repository.get(userKey);
        if (user != null && user.getOrdersToReview() != null) {
            Order order;
            for (String orderKey : user.getOrdersToReview().keySet()) {
                order = orderRepository.get(orderKey);
                orders.add(order);
            }
        }

        return orders;
    }
} public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onResume() {
        super.onResume();
        Preferences.init(getApplicationContext());
    }

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        Preferences.init(getApplicationContext());
    }

} public class Preferences {

    private static final String PACKAGE_NAME = "dev.wisebite.wisebite";
    private static final String EMAIL_KEY = "user_email";

    private static SharedPreferences prefs;

    public static void init(Context context) {
        prefs = context.getSharedPreferences(PACKAGE_NAME, Context.MODE_PRIVATE);
    }

    public static String getCurrentUserEmail() {
        if (prefs == null){
            return "";
        }
        return prefs.getString(EMAIL_KEY, "");
    }

    public static void setCurrentUserEmail(String email) {
        if (prefs != null){
            prefs.edit().putString(EMAIL_KEY, email.split("\\.")[0]).apply();
        }
    }

} public class Utils {

    private static Menu tempMenu;
    private static Date tempDate;
    private static Integer loaded = 0;

    @SuppressWarnings("deprecation")
    public static String parseStartEndDate(TimePicker firstTimePicker, TimePicker secondTimePicker) {
        int firstHour, firstMinute, secondHour, secondMinute;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            firstHour = firstTimePicker.getHour();
            firstMinute = firstTimePicker.getMinute();
            secondHour = secondTimePicker.getHour();
            secondMinute = secondTimePicker.getMinute();
        } else {
            firstHour = firstTimePicker.getCurrentHour();
            firstMinute = firstTimePicker.getCurrentMinute();
            secondHour = secondTimePicker.getCurrentHour();
            secondMinute = secondTimePicker.getCurrentMinute();
        }

        return datesToString(firstHour, firstMinute, secondHour, secondMinute);
    }

    public static String parseStartEndDate(Date startDate, Date endDate) {
        int firstHour, firstMinute, secondHour, secondMinute;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        firstHour = calendar.get(Calendar.HOUR_OF_DAY);
        firstMinute = calendar.get(Calendar.MINUTE);

        calendar.setTime(endDate);
        secondHour = calendar.get(Calendar.HOUR_OF_DAY);
        secondMinute = calendar.get(Calendar.MINUTE);

        return datesToString(firstHour, firstMinute, secondHour, secondMinute);
    }

    @SuppressWarnings("deprecation")
    public static OpenTime createOpenTimeByTimePicker(TimePicker firstTimePicker, TimePicker secondTimePicker, Integer viewId) {
        int dayOfTheWeek = parseViewIdToDayOfWeek(viewId);

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTimeInMillis(0);
        startCalendar.set(Calendar.DAY_OF_WEEK, dayOfTheWeek);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            startCalendar.set(Calendar.HOUR_OF_DAY, firstTimePicker.getHour());
            startCalendar.set(Calendar.MINUTE, firstTimePicker.getMinute());
        } else {
            startCalendar.set(Calendar.HOUR_OF_DAY, firstTimePicker.getCurrentHour());
            startCalendar.set(Calendar.MINUTE, firstTimePicker.getCurrentMinute());
        }


        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTimeInMillis(0);
        endCalendar.set(Calendar.DAY_OF_WEEK, dayOfTheWeek);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            endCalendar.set(Calendar.HOUR_OF_DAY, secondTimePicker.getHour());
            endCalendar.set(Calendar.MINUTE, secondTimePicker.getMinute());
        } else {
            endCalendar.set(Calendar.HOUR_OF_DAY, secondTimePicker.getCurrentHour());
            endCalendar.set(Calendar.MINUTE, secondTimePicker.getCurrentMinute());
        }

        return OpenTime.builder()
                    .startDate(startCalendar.getTime())
                    .endDate(endCalendar.getTime())
                    .build();
    }

    public static void setTempMenu(Menu menu) {
        tempMenu = menu;
    }

    public static Menu getTempMenu() {
        return tempMenu;
    }

    public static Integer getLoaded() { return loaded; }

    public static void increaseLoaded() { ++loaded; }

    public static String toStringWithTwoDecimals(double d) {
        d = Math.round(d * 100);
        d = d/100;
        return String.valueOf(d);
    }

    public static String getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);

        String result = "";
        if (hour < 10) result += '0';
        result += String.valueOf(hour) + ':';
        if (minute < 10) result += '0';
        result += String.valueOf(minute);

        return result;
    }

    private static String datesToString(int firstHour, int firstMinute, int secondHour, int secondMinute) {
        String parsed = "";
        if (firstHour < 10) parsed += '0';
        parsed += String.valueOf(firstHour) + ':';
        if (firstMinute < 10) parsed += '0';
        parsed += String.valueOf(firstMinute);

        parsed += " - ";

        if (secondHour < 10) parsed += '0';
        parsed += String.valueOf(secondHour) + ':';
        if (secondMinute < 10) parsed += '0';
        parsed += String.valueOf(secondMinute);
        return parsed;
    }

    public static int parseViewIdToDayOfWeek(Integer viewId) {
        switch (viewId) {
            case R.id.monday_date_picker:
                return Calendar.MONDAY;
            case R.id.tuesday_date_picker:
                return Calendar.TUESDAY;
            case R.id.wednesday_date_picker:
                return Calendar.WEDNESDAY;
            case R.id.thursday_date_picker:
                return Calendar.THURSDAY;
            case R.id.friday_date_picker:
                return Calendar.FRIDAY;
            case R.id.saturday_date_picker:
                return Calendar.SATURDAY;
            case R.id.sunday_date_picker:
                return Calendar.SUNDAY;
            default:
                return 0;
        }
    }

    public static String skipAts(String email) {
        return email.replaceAll("\\.", "@");
    }

    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    public static void setAnalyticsDate(Date date) {
        tempDate = date;
    }

    public static Date getAnalyticsDate() {
        return tempDate;
    }
}
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import dev.wisebite.wisebite.R;
import dev.wisebite.wisebite.adapter.DetailAdapter;
import dev.wisebite.wisebite.domain.Dish;
import dev.wisebite.wisebite.domain.Menu;
import dev.wisebite.wisebite.domain.OpenTime;
import dev.wisebite.wisebite.domain.Restaurant;
import dev.wisebite.wisebite.service.RestaurantService;
import dev.wisebite.wisebite.service.ServiceFactory;
import dev.wisebite.wisebite.service.UserService;
import dev.wisebite.wisebite.utils.BaseActivity;
import dev.wisebite.wisebite.utils.Preferences;
import dev.wisebite.wisebite.utils.Utils;
package dev.wisebite.wisebite.activity;




public class GetRestaurantActivity extends BaseActivity {

    public static final String RESTAURANT_ID = "RESTAURANT_ID";

    private RestaurantService restaurantService;
    private UserService userService;
    private Restaurant restaurant;
    private String restaurantId;

    private FloatingActionButton fab;
    private LayoutInflater inflater;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_get_restaurant);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        if (getIntent().getSerializableExtra(RESTAURANT_ID) != null) {
            this.restaurantId = getIntent().getExtras().getString(RESTAURANT_ID);
        }

        restaurantService = ServiceFactory.getRestaurantService(GetRestaurantActivity.this);
        userService = ServiceFactory.getUserService(GetRestaurantActivity.this);
        restaurant = restaurantService.get(restaurantId);
        inflater = LayoutInflater.from(GetRestaurantActivity.this);

        fab = (FloatingActionButton) findViewById(R.id.fab_add);

        initializeGeneralInfo();
        initializeOpenTimes();
        initializeDishes();
        initializeMenus();
    }

    @Override
    public boolean onCreateOptionsMenu(android.view.Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.get_restaurant, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            case R.id.action_reviews:
                Intent intent = new Intent(GetRestaurantActivity.this, ReviewListActivity.class);
                intent.putExtra(ReviewListActivity.DISH_ID, restaurantId);
                startActivity(intent);
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * Initialize general restaurant information
     */
    private void initializeGeneralInfo() {
        setTitle(restaurant.getName());
        TextView description, location, phone, website, numberOfTables, averagePunctuation;
        description = (TextView) findViewById(R.id.description_refill);
        location = (TextView) findViewById(R.id.location_refill);
        phone = (TextView) findViewById(R.id.phone_refill);
        website = (TextView) findViewById(R.id.website_refill);
        numberOfTables = (TextView) findViewById(R.id.number_of_tables_refill);
        averagePunctuation = (TextView) findViewById(R.id.average_punctuation_refill);
        description.setText(restaurant.getDescription());
        location.setText(restaurant.getLocation());
        phone.setText(String.valueOf(restaurant.getPhone()));
        website.setText(restaurant.getWebsite());
        numberOfTables.setText(String.valueOf(restaurant.getNumberOfTables() + " tables"));
        averagePunctuation.setText(restaurantService.getAveragePunctuationOfRestaurant(restaurantId) == -1.0 ?
                "---" :
                Utils.toStringWithTwoDecimals(restaurantService.getAveragePunctuationOfRestaurant(restaurantId)) + " / 5.0");