public class FragmentAdapter extends FragmentStatePagerAdapter {

    private final List<Fragment> fragments = new ArrayList<>();
    private final List<String> fragmentTitles = new ArrayList<>();

    public FragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    public void addFragment(android.support.v4.app.Fragment fragment, String title) {
        fragments.add(fragment);
        fragmentTitles.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return fragmentTitles.get(position);
    }
} public class KitchenAdapter extends RecyclerView.Adapter<KitchenAdapter.KitchenHolder> {

    private ArrayList<Order> orders;
    private Context context;

    private OrderService orderService;
    private UserService userService;

    public KitchenAdapter(ArrayList<Order> ordersList, Context context) {
        this.orders = ordersList;
        this.context = context;
        this.orderService = ServiceFactory.getOrderService(context);
        this.userService = ServiceFactory.getUserService(context);
        notifyDataSetChanged();
        setListener();
    }

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

    @Override
    public void onBindViewHolder(KitchenHolder holder, int position) {
        Order current = orders.get(position);
        holder.item = current;
        holder.date.setText(Utils.getHour(current.getDate()));
        holder.ready.setText(String.format("%s%%", calculateReady(current)));
        initializeOrderItems(holder);
    }

    private void initializeOrderItems(KitchenHolder holder) {
        KitchenItemAdapter kitchenItemAdapter = new KitchenItemAdapter(orderService.getNonReadyOrderItems(holder.item),
                context, holder.item);
        RecyclerView recyclerView = (RecyclerView) holder.view.findViewById(R.id.kitchen_order_items_list);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
        assert recyclerView != null;
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(kitchenItemAdapter);
    }

    private String calculateReady(Order current) {
        return Utils.toStringWithTwoDecimals(orderService.getReadyOfOrder(current.getId()));
    }

    @Override
    public int getItemCount() {
        return orders.size();
    }

    class KitchenHolder extends RecyclerView.ViewHolder {

        public View view;
        Order item;
        TextView date;
        TextView ready;
        RecyclerView recyclerView;

        KitchenHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.date = (TextView) itemView.findViewById(R.id.date_order);
            this.ready = (TextView) itemView.findViewById(R.id.ready);
            this.recyclerView = (RecyclerView) itemView.findViewById(R.id.kitchen_order_items_list);
        }
    }

    private void setListener() {
        orderService.setOnChangedListener(new Repository.OnChangedListener() {
            @Override
            public void onChanged(EventType type) {
                if (type.equals(EventType.Full)) {
                    orders = orderService.getNonReadyOrders(userService.getFirstRestaurantId(Preferences.getCurrentUserEmail()));
                    notifyDataSetChanged();
                }
            }
        });
    }
} public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.OrderHolder> {

    private ArrayList<Order> orders;
    private Context context;
    private OrderService orderService;
    private UserService userService;

    public OrderAdapter(ArrayList<Order> ordersList, Context context) {
        this.orders = ordersList;
        this.context = context;
        this.orderService = ServiceFactory.getOrderService(context);
        this.userService = ServiceFactory.getUserService(context);
        notifyDataSetChanged();
        setListener();
    }

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

    @SuppressWarnings("deprecation")
    @Override
    public void onBindViewHolder(OrderHolder holder, int position) {
        Order current = orders.get(position);
        holder.item = current;
        holder.numberTable.setText(String.valueOf("Table " + current.getTableNumber()));
        holder.price.setText(String.valueOf(calculatePrice(current) + " €"));
        holder.ready.setText(String.valueOf("Ready: " + calculateReady(current) + "%"));
        holder.delivered.setText(String.valueOf("Delivered: " + calculateDelivered(current) + "%"));
        holder.paid.setText(String.valueOf("Paid: " + calculatePaid(current) + "%"));
        if (calculateReady(current).equals(calculateDelivered(current))) {
            holder.view.setBackgroundColor(context.getResources().getColor(R.color.white));
        } else {
            holder.view.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
        }
    }

    private String calculatePrice(Order current) {
        return Utils.toStringWithTwoDecimals(orderService.getPriceOfOrder(current.getId()));
    }

    private String calculateReady(Order current) {
        return Utils.toStringWithTwoDecimals(orderService.getReadyOfOrder(current.getId()));
    }

    private String calculateDelivered(Order current) {
        return Utils.toStringWithTwoDecimals(orderService.getDeliveredOfOrder(current.getId()));
    }

    private String calculatePaid(Order current) {
        return Utils.toStringWithTwoDecimals(orderService.getPaidOfOrder(current.getId()));
    }

    @Override
    public int getItemCount() {
        return orders.size();
    }

    class OrderHolder extends RecyclerView.ViewHolder {

        public View view;
        Order item;
        TextView numberTable;
        TextView price;
        TextView ready;
        TextView delivered;
        TextView paid;

        OrderHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.numberTable = (TextView) itemView.findViewById(R.id.table_number);
            this.price = (TextView) itemView.findViewById(R.id.price);
            this.ready = (TextView) itemView.findViewById(R.id.ready);
            this.delivered = (TextView) itemView.findViewById(R.id.delivered);
            this.paid = (TextView) itemView.findViewById(R.id.paid);

            this.view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(v.getContext(), GetOrderActivity.class);
                    intent.putExtra(GetOrderActivity.INTENT_ORDER, item.getId());
                    v.getContext().startActivity(intent);
                }
            });
        }
    }

    private void setListener() {
        orderService.setOnChangedListener(new Repository.OnChangedListener() {
            @Override
            public void onChanged(EventType type) {
                if (type.equals(EventType.Full)) {
                    orders = orderService.getActiveOrders(userService.getFirstRestaurantId(Preferences.getCurrentUserEmail()));
                    notifyDataSetChanged();
                }
            }
        });
    }
} public class OrderItemAdapter extends RecyclerView.Adapter<OrderItemAdapter.OrderItemHolder> {

    private ArrayList<OrderItem> orderItems;
    private final Order order;

    private OrderService orderService;
    private OrderItemService orderItemService;
    private Context context;

    public OrderItemAdapter(ArrayList<OrderItem> orderItems, Context context, Order order) {
        this.orderItems = orderItems;
        this.order = order;

        this.orderService = ServiceFactory.getOrderService(context);
        this.orderItemService = ServiceFactory.getOrderItemService(context);
        this.context = context;
        notifyDataSetChanged();
    }

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

    @Override
    public void onBindViewHolder(final OrderItemHolder holder, int position) {
        final OrderItem current = orderItems.get(position);
        holder.item = current;
        holder.name.setText(orderItemService.getDishName(current));
        setFlags(holder);
    }

    @Override
    public int getItemCount() {
        return orderItems.size();
    }

    class OrderItemHolder extends RecyclerView.ViewHolder {

        public View view;
        OrderItem item;
        TextView name;
        TextView ready;
        TextView delivered;
        TextView paid;
        FloatingActionButton mark;

        OrderItemHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.name = (TextView) itemView.findViewById(R.id.name);
            this.ready = (TextView) itemView.findViewById(R.id.ready);
            this.delivered = (TextView) itemView.findViewById(R.id.delivered);
            this.paid = (TextView) itemView.findViewById(R.id.paid);
            this.mark = (FloatingActionButton) itemView.findViewById(R.id.fab);
            this.mark.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    orderService.setDelivered(item, true, order);
                    notifyDataSetChanged();
                }
            });
        }
    }

    private void setFlags(OrderItemHolder holder) {
        Activity activity = (Activity) context;

        if (holder.item.isReady()) {
            holder.ready.setVisibility(View.VISIBLE);

            if (activity instanceof GetOrderActivity) {
                if (!holder.item.isDelivered()) {
                    holder.mark.setVisibility(View.VISIBLE);
                } else {
                    holder.mark.setVisibility(View.GONE);
                }
            }

        }
        if (holder.item.isDelivered()) {
            holder.delivered.setVisibility(View.VISIBLE);
        }
        if (holder.item.isPaid()) {
            holder.paid.setVisibility(View.VISIBLE);
        }
    }

} public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.OrderHolder> {

    private List<Restaurant> restaurants;
    private RestaurantService restaurantService;

    public RestaurantAdapter(List<Restaurant> restaurantsList, Context context) {
        this.restaurants = restaurantsList;
        this.restaurantService = ServiceFactory.getRestaurantService(context);
        notifyDataSetChanged();
    }

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

    @Override
    public void onBindViewHolder(OrderHolder holder, int position) {
        Restaurant restaurant = restaurants.get(position);
        float rating = (float) restaurantService.getAveragePunctuationOfRestaurant(restaurant.getId());

        holder.item = restaurant;
        holder.name.setText(restaurant.getName());

        if (rating != -1) {
            holder.ratingBar.setVisibility(View.VISIBLE);
            holder.ratingBar.setRating(rating);
        }
        else holder.ratingBar.setVisibility(View.INVISIBLE);

        holder.description.setText(restaurant.getDescription());
        holder.daysOpen.setText(String.valueOf(calculateDaysOpen(restaurant) + " open days"));
        holder.dishesCount.setText(String.valueOf(calculateDishesCount(restaurant) + " different dishes"));
        holder.menusCount.setText(String.valueOf(calculateMenusCount(restaurant) + " different menus"));
    }

    private String calculateDaysOpen(Restaurant current) {
        return String.valueOf(restaurantService.getDaysOpen(current));
    }

    private String calculateDishesCount(Restaurant current) {
        return String.valueOf(restaurantService.getDishesCount(current));
    }

    private String calculateMenusCount(Restaurant current) {
        return String.valueOf(restaurantService.getMenusCount(current));
    }

    @Override
    public int getItemCount() {
        return restaurants.size();
    }

    class OrderHolder extends RecyclerView.ViewHolder {

        public View view;
        Restaurant item;
        TextView name;
        RatingBar ratingBar;
        TextView description;
        TextView daysOpen;
        TextView dishesCount;
        TextView menusCount;

        OrderHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.name = (TextView) itemView.findViewById(R.id.name);
            this.ratingBar = (RatingBar) itemView.findViewById(R.id.rating_bar);
            this.description = (TextView) itemView.findViewById(R.id.description);
            this.daysOpen = (TextView) itemView.findViewById(R.id.days_open);
            this.dishesCount = (TextView) itemView.findViewById(R.id.dishes_count);
            this.menusCount = (TextView) itemView.findViewById(R.id.menus_count);

            this.view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(v.getContext(), GetRestaurantActivity.class);
                    intent.putExtra(GetRestaurantActivity.RESTAURANT_ID, item.getId());
                    v.getContext().startActivity(intent);
                }
            });
        }
    }

} public class ReviewOrderAdapter extends RecyclerView.Adapter<ReviewOrderAdapter.OrderHolder> {

    private List<Order> orders;
    private OrderService orderService;
    private UserService userService;

    public ReviewOrderAdapter(List<Order> orderList, Context context) {
        this.orders = orderList;
        this.orderService = ServiceFactory.getOrderService(context);
        this.userService = ServiceFactory.getUserService(context);
        notifyDataSetChanged();
        setListener();
    }

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

    @Override
    public void onBindViewHolder(OrderHolder holder, int position) {
        Order order = orders.get(position);
        holder.item = order;
        holder.name.setText(orderService.getRestaurantName(order.getId()));
        holder.description.setText(orderService.getDescription(order.getId()));
    }

    @Override
    public int getItemCount() {
        return orders.size();
    }

    class OrderHolder extends RecyclerView.ViewHolder {

        public View view;
        Order item;
        TextView name;
        TextView description;

        OrderHolder(View itemView) {
            super(itemView);
            this.view = itemView;
            this.name = (TextView) itemView.findViewById(R.id.name);
            this.description = (TextView) itemView.findViewById(R.id.description);

            this.view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(v.getContext(), ReviewActivity.class);
                    intent.putExtra(ReviewActivity.ORDER_ID, item.getId());
                    v.getContext().startActivity(intent);
                }
            });
        }
    }

    private void setListener() {
        userService.setOnChangedListener(new Repository.OnChangedListener() {
            @Override
            public void onChanged(EventType type) {
                if (type.equals(EventType.Full)) {
                    orders = userService.getOrdersToReview(Preferences.getCurrentUserEmail());
                    notifyDataSetChanged();
                }
            }
        });
    }

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

    private String id;
    private Date date;
    private Integer tableNumber;
    private Date lastDate;

    private Map<String, Object> orderItems;

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

    @Override
    public void setId(String id) {
        this.id = id;
    }
} @Getter
@Setter
@AllArgsConstructor(suppressConstructorProperties = true)
@NoArgsConstructor
@ToString
@Builder
public class OrderItem implements Entity {

    private String id;
    private String differentFeature;
    private boolean paid;
    private boolean ready;
    private boolean delivered;
    private String dishId;
    private String menuId;

    @Override
    public String getId() {
        return this.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;
    }

} @SuppressLint("ValidFragment")
public class AnalyticsDayFragment extends Fragment {

    private RestaurantService restaurantService;
    private String restaurantId;

    public AnalyticsDayFragment(Context context, String restaurantId) {
        this.restaurantService = ServiceFactory.getRestaurantService(context);
        this.restaurantId = restaurantId;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.analytics_fragment, container, false);

        LinearLayout mainFragmentLayout = (LinearLayout) view.findViewById(R.id.main_fragment_layout);
        //noinspection deprecation
        mainFragmentLayout.setBackgroundColor(getResources().getColor(R.color.day_color));

        TextView analyticsDate = (TextView) view.findViewById(R.id.analytics_date_refill);
        @SuppressLint("SimpleDateFormat") SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
        analyticsDate.setText(simpleDateFormat.format(Utils.getAnalyticsDate()));

        initializeValues(view);
        initializePieCharts(view);
        initializeBarCharts(view);

        return view;

    }

    private void initializeValues(View view) {
        TextView numberOfOrders = (TextView) view.findViewById(R.id.number_of_orders_refill);
        TextView averagePrice = (TextView) view.findViewById(R.id.average_price_refill);
        TextView totalEarned = (TextView) view.findViewById(R.id.total_earned_refill);
        TextView bestDish = (TextView) view.findViewById(R.id.best_dish_refill);
        TextView worstDish = (TextView) view.findViewById(R.id.worst_dish_refill);
        TextView bestMenu = (TextView) view.findViewById(R.id.best_menu_refill);
        TextView worstMenu = (TextView) view.findViewById(R.id.worst_menu_refill);
        TextView bestTimeRange = (TextView) view.findViewById(R.id.best_time_range_refill);
        TextView averageTime = (TextView) view.findViewById(R.id.average_time_refill);
        TextView averagePunctuation = (TextView) view.findViewById(R.id.average_punctuation_refill);
        TextView reviewsCount = (TextView) view.findViewById(R.id.reviews_count_refill);

        numberOfOrders.setText(String.valueOf(restaurantService.getOrdersCount(restaurantId, Calendar.DATE)));
        averagePrice.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getAveragePrice(restaurantId, Calendar.DATE))));
        totalEarned.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getTotalEarned(restaurantId, Calendar.DATE))));
        bestDish.setText(restaurantService.getBestDish(restaurantId, Calendar.DATE));
        worstDish.setText(restaurantService.getWorstDish(restaurantId, Calendar.DATE));
        bestMenu.setText(restaurantService.getBestMenu(restaurantId, Calendar.DATE));
        worstMenu.setText(restaurantService.getWorstMenu(restaurantId, Calendar.DATE));
        bestTimeRange.setText(restaurantService.getBestTimeRange(restaurantId, Calendar.DATE));
        averageTime.setText(restaurantService.getAverageTime(restaurantId, Calendar.DATE));
        averagePunctuation.setText(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.DATE) == -1.0 ?
                "---" :
                Utils.toStringWithTwoDecimals(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.DATE)));
        reviewsCount.setText(String.valueOf(restaurantService.getReviewsCount(restaurantId, Calendar.DATE)));
    }

    private void createPieChart(View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        PieChart pieChart = (PieChart) view.findViewById(id);
        pieChart.setRotationEnabled(true);
        pieChart.setHoleRadius(0);
        pieChart.setTransparentCircleAlpha(0);

        Description description = new Description();
        description.setText("");
        pieChart.setDescription(description);

        ArrayList<PieEntry> yEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) yEntries.add(new PieEntry(yData[i], xData[i]));

        PieDataSet pieDataSet = new PieDataSet(yEntries, "");
        pieDataSet.setSliceSpace(3);
        pieDataSet.setSelectionShift(5);

        Legend legend = pieChart.getLegend();
        //noinspection deprecation
        legend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
        legend.setWordWrapEnabled(true);

        ArrayList<Integer> colors = new ArrayList<>();
        for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c);
        for (int c : ColorTemplate.JOYFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.COLORFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.LIBERTY_COLORS) colors.add(c);
        for (int c : ColorTemplate.PASTEL_COLORS) colors.add(c);
        colors.add(ColorTemplate.getHoloBlue());
        pieDataSet.setColors(colors);

        PieData pieData = new PieData(pieDataSet);
        pieData.setValueFormatter(new PercentFormatter());
        pieData.setValueTextSize(15f);
        pieData.setValueTextColor(Color.BLACK);

        pieChart.setData(pieData);
        pieChart.setEntryLabelTextSize(0);
        pieChart.invalidate();
    }

    private void createBarChart(final View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        BarChart barChart = (BarChart) view.findViewById(id);

        ArrayList<BarEntry> barEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) barEntries.add(new BarEntry(i, yData[i]));

        BarDataSet barDataSet;
        barDataSet = new BarDataSet(barEntries, "");
        barDataSet.setColors(ColorTemplate.COLORFUL_COLORS);

        ArrayList<IBarDataSet> dataSets = new ArrayList<>();
        dataSets.add(barDataSet);

        YAxis left = barChart.getAxisLeft();
        left.setDrawLabels(false);
        XAxis xAxis = barChart.getXAxis();
        xAxis.setValueFormatter(new MyXAxisValueFormatter(xData));

        BarData barData = new BarData(dataSets);
        barChart.setData(barData);

        Description description = new Description();
        description.setText("");
        barChart.setDescription(description);

        barChart.getLegend().setEnabled(false);

        barChart.animateY(1000);
        barChart.setHorizontalScrollBarEnabled(true);
        barChart.invalidate();

        barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, Highlight h) {
                Snackbar.make(view, "Time range: " + xData[(int) e.getX()], Snackbar.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected() {

            }
        });
    }

    private void initializePieCharts(final View view) {
        PieChartData dishesData = restaurantService.getAllDishesCount(restaurantId, Calendar.DATE);
        if (!dishesData.isEmpty()) {
            view.findViewById(R.id.mock_first_pie).setVisibility(View.GONE);
            createPieChart(view, dishesData, R.id.best_dishes_pie_chart);
        } else {
            view.findViewById(R.id.best_dishes_pie_chart).setVisibility(View.GONE);
        }

        PieChartData menusData = restaurantService.getAllMenusCount(restaurantId, Calendar.DATE);
        if (!menusData.isEmpty()) {
            view.findViewById(R.id.mock_second_pie).setVisibility(View.GONE);
            createPieChart(view, menusData, R.id.best_menus_pie_chart);
        } else {
            view.findViewById(R.id.best_menus_pie_chart).setVisibility(View.GONE);
        }
    }

    private void initializeBarCharts(final View view) {
        PieChartData ordersData = restaurantService.getAllOrdersCount(restaurantId, Calendar.DATE);
        if (!ordersData.isEmpty()) {
            view.findViewById(R.id.mock_third_pie).setVisibility(View.GONE);
            createBarChart(view, ordersData, R.id.orders_time_range);
        } else {
            view.findViewById(R.id.orders_time_range).setVisibility(View.GONE);
        }
    }

} @SuppressLint("ValidFragment")
public class AnalyticsMonthFragment extends Fragment {

    private RestaurantService restaurantService;
    private String restaurantId;

    public AnalyticsMonthFragment(Context context, String restaurantId) {
        this.restaurantService = ServiceFactory.getRestaurantService(context);
        this.restaurantId = restaurantId;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.analytics_fragment, container, false);

        LinearLayout mainFragmentLayout = (LinearLayout) view.findViewById(R.id.main_fragment_layout);
        //noinspection deprecation
        mainFragmentLayout.setBackgroundColor(getResources().getColor(R.color.month_color));

        TextView analyticsDate = (TextView) view.findViewById(R.id.analytics_date_refill);
        @SuppressLint("SimpleDateFormat") SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
        analyticsDate.setText(simpleDateFormat.format(Utils.getAnalyticsDate()));

        initializeValues(view);
        initializePieCharts(view);
        initializeBarCharts(view);

        return view;

    }

    private void initializeValues(View view) {
        TextView numberOfOrders = (TextView) view.findViewById(R.id.number_of_orders_refill);
        TextView averagePrice = (TextView) view.findViewById(R.id.average_price_refill);
        TextView totalEarned = (TextView) view.findViewById(R.id.total_earned_refill);
        TextView bestDish = (TextView) view.findViewById(R.id.best_dish_refill);
        TextView worstDish = (TextView) view.findViewById(R.id.worst_dish_refill);
        TextView bestMenu = (TextView) view.findViewById(R.id.best_menu_refill);
        TextView worstMenu = (TextView) view.findViewById(R.id.worst_menu_refill);
        TextView bestTimeRange = (TextView) view.findViewById(R.id.best_time_range_refill);
        TextView averageTime = (TextView) view.findViewById(R.id.average_time_refill);
        TextView averagePunctuation = (TextView) view.findViewById(R.id.average_punctuation_refill);
        TextView reviewsCount = (TextView) view.findViewById(R.id.reviews_count_refill);

        numberOfOrders.setText(String.valueOf(restaurantService.getOrdersCount(restaurantId, Calendar.MONTH)));
        averagePrice.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getAveragePrice(restaurantId, Calendar.MONTH))));
        totalEarned.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getTotalEarned(restaurantId, Calendar.MONTH))));
        bestDish.setText(restaurantService.getBestDish(restaurantId, Calendar.MONTH));
        worstDish.setText(restaurantService.getWorstDish(restaurantId, Calendar.MONTH));
        bestMenu.setText(restaurantService.getBestMenu(restaurantId, Calendar.MONTH));
        worstMenu.setText(restaurantService.getWorstMenu(restaurantId, Calendar.MONTH));
        bestTimeRange.setText(restaurantService.getBestTimeRange(restaurantId, Calendar.MONTH));
        averageTime.setText(restaurantService.getAverageTime(restaurantId, Calendar.MONTH));
        averagePunctuation.setText(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.MONTH) == -1.0 ?
                "---" :
                Utils.toStringWithTwoDecimals(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.MONTH)));
        reviewsCount.setText(String.valueOf(restaurantService.getReviewsCount(restaurantId, Calendar.MONTH)));

    }

    private void createPieChart(View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        PieChart pieChart = (PieChart) view.findViewById(id);
        pieChart.setRotationEnabled(true);
        pieChart.setHoleRadius(0);
        pieChart.setTransparentCircleAlpha(0);

        Description description = new Description();
        description.setText("");
        pieChart.setDescription(description);

        ArrayList<PieEntry> yEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) yEntries.add(new PieEntry(yData[i], xData[i]));

        PieDataSet pieDataSet = new PieDataSet(yEntries, "");
        pieDataSet.setSliceSpace(3);
        pieDataSet.setSelectionShift(5);

        Legend legend = pieChart.getLegend();
        //noinspection deprecation
        legend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
        legend.setWordWrapEnabled(true);

        ArrayList<Integer> colors = new ArrayList<>();
        for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c);
        for (int c : ColorTemplate.JOYFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.COLORFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.LIBERTY_COLORS) colors.add(c);
        for (int c : ColorTemplate.PASTEL_COLORS) colors.add(c);
        colors.add(ColorTemplate.getHoloBlue());
        pieDataSet.setColors(colors);

        PieData pieData = new PieData(pieDataSet);
        pieData.setValueFormatter(new PercentFormatter());
        pieData.setValueTextSize(15f);
        pieData.setValueTextColor(Color.BLACK);

        pieChart.setData(pieData);
        pieChart.setEntryLabelTextSize(0);
        pieChart.invalidate();
    }

    private void createBarChart(final View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        BarChart barChart = (BarChart) view.findViewById(id);

        ArrayList<BarEntry> barEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) barEntries.add(new BarEntry(i, yData[i]));

        BarDataSet barDataSet;
        barDataSet = new BarDataSet(barEntries, "");
        barDataSet.setColors(ColorTemplate.COLORFUL_COLORS);

        ArrayList<IBarDataSet> dataSets = new ArrayList<>();
        dataSets.add(barDataSet);

        YAxis left = barChart.getAxisLeft();
        left.setDrawLabels(false);
        XAxis xAxis = barChart.getXAxis();
        xAxis.setValueFormatter(new MyXAxisValueFormatter(xData));

        BarData barData = new BarData(dataSets);
        barChart.setData(barData);

        Description description = new Description();
        description.setText("");
        barChart.setDescription(description);

        barChart.getLegend().setEnabled(false);

        barChart.animateY(1000);
        barChart.setHorizontalScrollBarEnabled(true);
        barChart.invalidate();

        barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, Highlight h) {
                Snackbar.make(view, "Time range: " + xData[(int) e.getX()], Snackbar.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected() {

            }
        });
    }

    private void initializePieCharts(final View view) {
        PieChartData dishesData = restaurantService.getAllDishesCount(restaurantId, Calendar.MONTH);
        if (!dishesData.isEmpty()) {
            view.findViewById(R.id.mock_first_pie).setVisibility(View.GONE);
            createPieChart(view, dishesData, R.id.best_dishes_pie_chart);
        } else {
            view.findViewById(R.id.best_dishes_pie_chart).setVisibility(View.GONE);
        }

        PieChartData menusData = restaurantService.getAllMenusCount(restaurantId, Calendar.MONTH);
        if (!menusData.isEmpty()) {
            view.findViewById(R.id.mock_second_pie).setVisibility(View.GONE);
            createPieChart(view, menusData, R.id.best_menus_pie_chart);
        } else {
            view.findViewById(R.id.best_menus_pie_chart).setVisibility(View.GONE);
        }
    }

    private void initializeBarCharts(final View view) {
        PieChartData ordersData = restaurantService.getAllOrdersCount(restaurantId, Calendar.MONTH);
        if (!ordersData.isEmpty()) {
            view.findViewById(R.id.mock_third_pie).setVisibility(View.GONE);
            createBarChart(view, ordersData, R.id.orders_time_range);
        } else {
            view.findViewById(R.id.orders_time_range).setVisibility(View.GONE);
        }
    }

} @SuppressLint("ValidFragment")
public class AnalyticsWeekFragment extends Fragment {

    private RestaurantService restaurantService;
    private String restaurantId;

    public AnalyticsWeekFragment(Context context, String restaurantId) {
        this.restaurantService = ServiceFactory.getRestaurantService(context);
        this.restaurantId = restaurantId;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.analytics_fragment, container, false);

        LinearLayout mainFragmentLayout = (LinearLayout) view.findViewById(R.id.main_fragment_layout);
        //noinspection deprecation
        mainFragmentLayout.setBackgroundColor(getResources().getColor(R.color.week_color));

        TextView analyticsDate = (TextView) view.findViewById(R.id.analytics_date_refill);
        @SuppressLint("SimpleDateFormat") SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
        analyticsDate.setText(simpleDateFormat.format(Utils.getAnalyticsDate()));

        initializeValues(view);
        initializePieCharts(view);
        initializeBarCharts(view);

        return view;

    }

    private void initializeValues(View view) {
        TextView numberOfOrders = (TextView) view.findViewById(R.id.number_of_orders_refill);
        TextView averagePrice = (TextView) view.findViewById(R.id.average_price_refill);
        TextView totalEarned = (TextView) view.findViewById(R.id.total_earned_refill);
        TextView bestDish = (TextView) view.findViewById(R.id.best_dish_refill);
        TextView worstDish = (TextView) view.findViewById(R.id.worst_dish_refill);
        TextView bestMenu = (TextView) view.findViewById(R.id.best_menu_refill);
        TextView worstMenu = (TextView) view.findViewById(R.id.worst_menu_refill);
        TextView bestTimeRange = (TextView) view.findViewById(R.id.best_time_range_refill);
        TextView averageTime = (TextView) view.findViewById(R.id.average_time_refill);
        TextView averagePunctuation = (TextView) view.findViewById(R.id.average_punctuation_refill);
        TextView reviewsCount = (TextView) view.findViewById(R.id.reviews_count_refill);

        numberOfOrders.setText(String.valueOf(restaurantService.getOrdersCount(restaurantId, Calendar.WEEK_OF_YEAR)));
        averagePrice.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getAveragePrice(restaurantId, Calendar.WEEK_OF_YEAR))));
        totalEarned.setText(String.format("%s €", Utils.toStringWithTwoDecimals(restaurantService.getTotalEarned(restaurantId, Calendar.WEEK_OF_YEAR))));
        bestDish.setText(restaurantService.getBestDish(restaurantId, Calendar.WEEK_OF_YEAR));
        worstDish.setText(restaurantService.getWorstDish(restaurantId, Calendar.WEEK_OF_YEAR));
        bestMenu.setText(restaurantService.getBestMenu(restaurantId, Calendar.WEEK_OF_YEAR));
        worstMenu.setText(restaurantService.getWorstMenu(restaurantId, Calendar.WEEK_OF_YEAR));
        bestTimeRange.setText(restaurantService.getBestTimeRange(restaurantId, Calendar.WEEK_OF_YEAR));
        averageTime.setText(restaurantService.getAverageTime(restaurantId, Calendar.WEEK_OF_YEAR));
        averagePunctuation.setText(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.WEEK_OF_YEAR) == -1.0 ?
                "---" :
                Utils.toStringWithTwoDecimals(restaurantService.getAveragePunctuationOfRestaurant(restaurantId, Calendar.WEEK_OF_YEAR)));
        reviewsCount.setText(String.valueOf(restaurantService.getReviewsCount(restaurantId, Calendar.WEEK_OF_YEAR)));

    }

    private void createPieChart(View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        PieChart pieChart = (PieChart) view.findViewById(id);
        pieChart.setRotationEnabled(true);
        pieChart.setHoleRadius(0);
        pieChart.setTransparentCircleAlpha(0);

        Description description = new Description();
        description.setText("");
        pieChart.setDescription(description);

        ArrayList<PieEntry> yEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) yEntries.add(new PieEntry(yData[i], xData[i]));

        PieDataSet pieDataSet = new PieDataSet(yEntries, "");
        pieDataSet.setSliceSpace(3);
        pieDataSet.setSelectionShift(5);

        Legend legend = pieChart.getLegend();
        //noinspection deprecation
        legend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
        legend.setWordWrapEnabled(true);

        ArrayList<Integer> colors = new ArrayList<>();
        for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c);
        for (int c : ColorTemplate.JOYFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.COLORFUL_COLORS) colors.add(c);
        for (int c : ColorTemplate.LIBERTY_COLORS) colors.add(c);
        for (int c : ColorTemplate.PASTEL_COLORS) colors.add(c);
        colors.add(ColorTemplate.getHoloBlue());
        pieDataSet.setColors(colors);

        PieData pieData = new PieData(pieDataSet);
        pieData.setValueFormatter(new PercentFormatter());
        pieData.setValueTextSize(15f);
        pieData.setValueTextColor(Color.BLACK);

        pieChart.setData(pieData);
        pieChart.setEntryLabelTextSize(0);
        pieChart.invalidate();
    }

    private void createBarChart(final View view, PieChartData data, int id) {
        float[] yData = data.getYData();
        final String[] xData = data.getXData();

        BarChart barChart = (BarChart) view.findViewById(id);

        ArrayList<BarEntry> barEntries = new ArrayList<>();
        for (int i = 0; i < yData.length; i++) barEntries.add(new BarEntry(i, yData[i]));

        BarDataSet barDataSet;
        barDataSet = new BarDataSet(barEntries, "");
        barDataSet.setColors(ColorTemplate.COLORFUL_COLORS);

        ArrayList<IBarDataSet> dataSets = new ArrayList<>();
        dataSets.add(barDataSet);

        YAxis left = barChart.getAxisLeft();
        left.setDrawLabels(false);
        XAxis xAxis = barChart.getXAxis();
        xAxis.setValueFormatter(new MyXAxisValueFormatter(xData));

        BarData barData = new BarData(dataSets);
        barChart.setData(barData);

        Description description = new Description();
        description.setText("");
        barChart.setDescription(description);

        barChart.getLegend().setEnabled(false);

        barChart.animateY(1000);
        barChart.setHorizontalScrollBarEnabled(true);
        barChart.invalidate();

        barChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, Highlight h) {
                Snackbar.make(view, "Time range: " + xData[(int) e.getX()], Snackbar.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected() {

            }
        });
    }

    private void initializePieCharts(final View view) {
        PieChartData dishesData = restaurantService.getAllDishesCount(restaurantId, Calendar.WEEK_OF_YEAR);
        if (!dishesData.isEmpty()) {
            view.findViewById(R.id.mock_first_pie).setVisibility(View.GONE);
            createPieChart(view, dishesData, R.id.best_dishes_pie_chart);
        } else {
            view.findViewById(R.id.best_dishes_pie_chart).setVisibility(View.GONE);
        }

        PieChartData menusData = restaurantService.getAllMenusCount(restaurantId, Calendar.WEEK_OF_YEAR);
        if (!menusData.isEmpty()) {
            view.findViewById(R.id.mock_second_pie).setVisibility(View.GONE);
            createPieChart(view, menusData, R.id.best_menus_pie_chart);
        } else {
            view.findViewById(R.id.best_menus_pie_chart).setVisibility(View.GONE);
        }
    }

    private void initializeBarCharts(final View view) {
        PieChartData ordersData = restaurantService.getAllOrdersCount(restaurantId, Calendar.WEEK_OF_YEAR);
        if (!ordersData.isEmpty()) {
            view.findViewById(R.id.mock_third_pie).setVisibility(View.GONE);
            createBarChart(view, ordersData, R.id.orders_time_range);
        } else {
            view.findViewById(R.id.orders_time_range).setVisibility(View.GONE);
        }
    }


} public class OrderService extends Service<Order> {

    private final Repository<OrderItem> orderItemRepository;
    private final Repository<Dish> dishRepository;
    private final Repository<Menu> menuRepository;
    private final Repository<Restaurant> restaurantRepository;
    private final Repository<User> userRepository;

    public OrderService(Repository<Order> repository,
                        Repository<OrderItem> orderItemRepository,
                        Repository<Dish> dishRepository,
                        Repository<Menu> menuRepository,
                        Repository<Restaurant> restaurantRepository,
                        Repository<User> userRepository) {
        super(repository);
        this.orderItemRepository = orderItemRepository;
        this.dishRepository = dishRepository;
        this.menuRepository = menuRepository;
        this.restaurantRepository = restaurantRepository;
        this.userRepository = userRepository;
    }

    public String getRestaurantName(String id) {
        for (Restaurant restaurant : restaurantRepository.all()) {
            if (restaurant.getExternalOrders() != null && restaurant.getExternalOrders().containsKey(id))
                return restaurant.getName();
        }
        return "";
    }

    public String getRestaurantId(String orderId) {
        for (Restaurant restaurant : restaurantRepository.all()) {
            if (restaurant.getExternalOrders() != null && restaurant.getExternalOrders().containsKey(orderId))
                return restaurant.getId();
        }
        return null;
    }

    public String getDescription(String id) {
        Order order = repository.get(id);

        String result = "Order at table number ";
        result += String.valueOf(order.getTableNumber());
        result += " on ";

        @SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
        result += dateFormat.format(order.getDate());

        return result;
    }

    public double getPriceOfOrder(String id) {
        Order order = repository.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;
    }

    public double getReadyOfOrder(String id) {
        Order order = repository.get(id);
        if (order == null) return 100.0;

        double total = order.getOrderItems().size();
        double ready = 0.0;

        for (String orderItemId : order.getOrderItems().keySet()) {
            OrderItem orderItem = orderItemRepository.get(orderItemId);
            if (orderItem == null) return 100.0;
            if (orderItem.isReady()) ++ready;
        }

        return (ready/total)*100.0;
    }

    public double getDeliveredOfOrder(String id) {
        Order order = repository.get(id);
        if (order == null) return 100.0;

        double total = order.getOrderItems().size();
        double delivered = 0.0;

        for (String orderItemId : order.getOrderItems().keySet()) {
            OrderItem orderItem = orderItemRepository.get(orderItemId);
            if (orderItem == null) return 100.0;
            if (orderItem.isDelivered()) ++delivered;
        }

        return (delivered/total)*100.0;
    }

    public double getPaidOfOrder(String id) {
        Order order = repository.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 ArrayList<Order> getActiveOrders(String restaurantId) {
        ArrayList<String> orderKeys = getOrdersOf(restaurantId);

        ArrayList<Order> orders = new ArrayList<>();
        for (String id : orderKeys) {
            Order order = repository.get(id);
            if (order == null) addNullActiveOrder(id, orders);
            else if (getPaidOfOrder(order.getId()) < 100.0) orders.add(order);
        }
        Collections.sort(orders, new OrderLastDateComparator());
        return orders;
    }

    public void addOrder(ArrayList<Dish> selectedDishes, Integer tableNumber, ArrayList<Menu> selectedMenus, String restaurantId) {
        Map<String, Object> orderItems = new LinkedHashMap<>();
        for (Dish dish : selectedDishes) {
            String insertedId = orderItemRepository.insert(OrderItem.builder()
                    .dishId(dish.getId())
                    .ready(false)
                    .delivered(false)
                    .paid(false)
                    .build()).getId();
            orderItems.put(insertedId, true);
        }
        for (Menu menu : selectedMenus) {
            ArrayList<String> dishesId = new ArrayList<>();
            for (String key : menu.getMainDishes().keySet()) dishesId.add(key);
            for (String key : menu.getSecondaryDishes().keySet()) dishesId.add(key);
            for (String key : menu.getOtherDishes().keySet()) dishesId.add(key);
            for (String dishId : dishesId) {
                Dish dish = dishRepository.get(dishId);
                String insertedId = orderItemRepository.insert(OrderItem.builder()
                        .dishId(dish.getId())
                        .menuId(menu.getId())
                        .ready(false)
                        .delivered(false)
                        .paid(false)
                        .build()).getId();
                orderItems.put(insertedId, true);
            }
        }
        String newId = repository.insert(Order.builder()
                .date(new Date())
                .tableNumber(tableNumber)
                .lastDate(new Date())
                .orderItems(orderItems)
                .build()).getId();

        User user = userRepository.get(Preferences.getCurrentUserEmail());
        Map<String, Object> myOrders = user.getMyOrders();
        if (myOrders == null) {
            myOrders = new LinkedHashMap<>();
        }
        myOrders.put(newId, true);
        user.setMyOrders(myOrders);
        userRepository.update(user);

        Restaurant restaurant = restaurantRepository.get(restaurantId);
        if (restaurant.getUsers() != null && !restaurant.getUsers().containsKey(user.getId())) {
            Map<String, Object> externalOrders = restaurant.getExternalOrders();
            if (externalOrders == null) {
                externalOrders = new LinkedHashMap<>();
            }
            externalOrders.put(newId, true);
            restaurant.setExternalOrders(externalOrders);
            restaurantRepository.update(restaurant);

            Map<String, Object> ordersToReview = user.getOrdersToReview();
            if (ordersToReview == null) {
                ordersToReview = new LinkedHashMap<>();
            }
            ordersToReview.put(newId, true);
            user.setOrdersToReview(ordersToReview);
            userRepository.update(user);
        }

    }

    public void setDelivered(OrderItem item, boolean b, Order order) {
        item.setDelivered(b);
        orderItemRepository.update(item);
        order.setLastDate(new Date());
        repository.update(order);
    }

    public void setReady(OrderItem item, boolean b, Order order) {
        item.setReady(b);
        orderItemRepository.update(item);
        order.setLastDate(new Date());
        repository.update(order);
    }

    public ArrayList<OrderItem> getOnlyDishItemsOf(Order order) {
        ArrayList<OrderItem> orderItems = new ArrayList<>();
        OrderItem orderItem;
        for (String orderItemId : order.getOrderItems().keySet()) {
            orderItem = orderItemRepository.get(orderItemId);
            if (orderItem != null) {
                if (orderItem.getMenuId() == null) {
                    orderItems.add(orderItem);
                }
            }
        }
        return orderItems;
    }

    public ArrayList<OrderItem> getOnlyMenuItemsOf(Order order) {
        ArrayList<OrderItem> orderItems = new ArrayList<>();
        OrderItem orderItem;
        for (String orderItemId : order.getOrderItems().keySet()) {
            orderItem = orderItemRepository.get(orderItemId);
            if (orderItem != null) {
                if (orderItem.getMenuId() != null) {
                    orderItems.add(orderItem);
                }
            }
        }
        return orderItems;
    }

    public void collectAll(Order order) {
        OrderItem orderItem;
        for (String key : order.getOrderItems().keySet()) {
            orderItem = orderItemRepository.get(key);
            orderItem.setPaid(true);
            orderItemRepository.update(orderItem);
        }
        order.setLastDate(new Date());
        repository.update(order);
    }

    public ArrayList<OrderItem> getItems(Order order, boolean collectCondition) {
        ArrayList<OrderItem> orderItems = new ArrayList<>();

        Map<String, List<OrderItem>> menuIds = new LinkedHashMap<>();
        OrderItem orderItem;
        for (String key : order.getOrderItems().keySet()) {
            orderItem = orderItemRepository.get(key);
            if (!collectCondition || !orderItem.isPaid()) {
                if (orderItem.getMenuId() == null) {
                    if (collectCondition || !containsDish(orderItem, orderItems))
                        orderItems.add(orderItem);
                } else {
                    List<OrderItem> count = menuIds.get(orderItem.getMenuId());
                    if (count == null) {
                        count = new ArrayList<>();
                    }
                    count.add(orderItem);
                    menuIds.put(orderItem.getMenuId(), count);
                }
            }
        }
        for (String key : menuIds.keySet()) {
            List<OrderItem> count = menuIds.get(key);
            Menu menu = menuRepository.get(key);
            Integer numberOptions = getNumberOptions(menu);
            for (int i = 0; i < count.size()/numberOptions; ++i) {
                if (collectCondition || !containsMenu(count.get(i), orderItems))
                    orderItems.add(count.get(i));
            }
        }

        return orderItems;
    }

    public void collectSomeItems(ArrayList<OrderItem> selectedItems, Order order) {
        List<String> menus = new ArrayList<>();
        for (OrderItem item : selectedItems) {
            if (item.getMenuId() == null) {
                item.setPaid(true);
                orderItemRepository.update(item);
            } else {
                menus.add(item.getMenuId());
            }
        }
        for (String id : menus) {
            Integer numberOptions = getNumberOptions(menuRepository.get(id));
            List<OrderItem> orderItems = new ArrayList<>();
            for (String key : order.getOrderItems().keySet()) {
                if (!orderItemRepository.get(key).isPaid()) {
                    orderItems.add(orderItemRepository.get(key));
                }
            }
            for (OrderItem item : orderItems) {
                if (item.getMenuId() != null && item.getMenuId().equals(id)) {
                    item.setPaid(true);
                    orderItemRepository.update(item);
                    if (--numberOptions == 0) break;
                }
            }
        }
        order.setLastDate(new Date());
        repository.update(order);
    }

    public boolean isPartially(Order order) {
        for (String key : order.getOrderItems().keySet()) {
            if (orderItemRepository.get(key).isPaid()) return true;
        }
        return false;
    }

    public void cancelOrder(Order order) {
        for (String key : order.getOrderItems().keySet()) {
            orderItemRepository.delete(key);
        }
        repository.delete(order.getId());

        for (Restaurant restaurant : restaurantRepository.all()) {
            if (restaurant.getExternalOrders() != null && restaurant.getExternalOrders().containsKey(order.getId())) {
                restaurant.getExternalOrders().remove(order.getId());
                restaurantRepository.update(restaurant);
            }
        }

        for (User user : userRepository.all()) {
            boolean change = false;

            Map<String, Object> ordersToReview = user.getOrdersToReview();
            if (ordersToReview != null) {
                if (ordersToReview.containsKey(order.getId())) {
                    ordersToReview.remove(order.getId());
                    user.setOrdersToReview(ordersToReview);
                    change = true;
                }
            }

            Map<String, Object> myOrders = user.getMyOrders();
            if (myOrders != null) {
                if (myOrders.containsKey(order.getId())) {
                    myOrders.remove(order.getId());
                    user.setMyOrders(myOrders);
                    change = true;
                }
            }

            if (change) userRepository.update(user);
        }
    }

    public ArrayList<Order> getNonReadyOrders(String restaurantId) {
        ArrayList<String> orderKeys = getOrdersOf(restaurantId);

        ArrayList<Order> orders = new ArrayList<>();
        for (String id : orderKeys) {
            Order order = repository.get(id);
            if (order == null) addNullNonReadyOrder(id, orders);
            else if (getReadyOfOrder(order.getId()) < 100.0) orders.add(order);
        }
        Collections.sort(orders, new OrderStartDateComparator());
        return orders;
    }

    public ArrayList<OrderItem> getNonReadyOrderItems(Order order) {
        ArrayList<OrderItem> result = new ArrayList<>();
        for (String key : order.getOrderItems().keySet()) {
            OrderItem orderItem = orderItemRepository.get(key);
            if (orderItem != null && !orderItem.isReady()) {
                result.add(orderItem);
            }
        }
        return result;
    }

    /** PRIVATE FUNCTIONS */

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

    private ArrayList<String> getOrdersOf(String restaurantId) {
        ArrayList<String> orderKeys = new ArrayList<>();
        Restaurant restaurant = restaurantRepository.get(restaurantId);
        for (String userId : restaurant.getUsers().keySet()) {
            User user = userRepository.get(userId);
            Map<String, Object> orderIds = user.getMyOrders();
            if (orderIds != null && !orderIds.isEmpty()) {
                for (String key : orderIds.keySet()) {
                    if (!isExternal(key)) orderKeys.add(key);
                }
            }
        }
        if (restaurant.getExternalOrders() != null) {
            orderKeys.addAll(restaurant.getExternalOrders().keySet());
        }
        return orderKeys;
    }

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

    private void addNullNonReadyOrder(final String id, final ArrayList<Order> orders) {
        new Thread(){
            @Override
            public void run() {
                Order order = repository.get(id);
                try {
                    while (order == null) {
                        sleep(1000);
                        order = repository.get(id);
                    }
                } catch (InterruptedException ex) {
                    // Catching exception
                } finally {
                    if (getReadyOfOrder(id) < 100.0) orders.add(order);
                }
            }
        }.start();
    }

    private void addNullActiveOrder(final String id, final ArrayList<Order> orders) {
        new Thread(){
            @Override
            public void run() {
                Order order = repository.get(id);
                try {
                    while (order == null) {
                        sleep(1000);
                        order = repository.get(id);
                    }
                } catch (InterruptedException ex) {
                    // Catching exception
                } finally {
                    if (getPaidOfOrder(id) < 100.0) orders.add(order);
                }
            }
        }.start();
    }

    private boolean containsDish(OrderItem orderItem, ArrayList<OrderItem> orderItems) {
        for (OrderItem item : orderItems) {
            if (item.getDishId().equals(orderItem.getDishId())) return true;
        }
        return false;
    }

    private boolean containsMenu(OrderItem orderItem, ArrayList<OrderItem> orderItems) {
        for (OrderItem item : orderItems) {
            if (item.getMenuId() != null && item.getMenuId().equals(orderItem.getMenuId()))
                return true;
        }
        return false;
    }
} 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.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.DatePicker;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import dev.wisebite.wisebite.R;
import dev.wisebite.wisebite.adapter.FragmentAdapter;
import dev.wisebite.wisebite.adapter.KitchenAdapter;
import dev.wisebite.wisebite.adapter.OrderAdapter;
import dev.wisebite.wisebite.adapter.OrderItemAdapter;
import dev.wisebite.wisebite.adapter.RestaurantAdapter;
import dev.wisebite.wisebite.adapter.ReviewOrderAdapter;
import dev.wisebite.wisebite.domain.Order;
import dev.wisebite.wisebite.domain.OrderItem;
import dev.wisebite.wisebite.domain.Restaurant;
import dev.wisebite.wisebite.fragment.AnalyticsDayFragment;
import dev.wisebite.wisebite.fragment.AnalyticsMonthFragment;
import dev.wisebite.wisebite.fragment.AnalyticsWeekFragment;
import dev.wisebite.wisebite.service.OrderService;
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 MainActivity extends BaseActivity
        implements NavigationView.OnNavigationItemSelectedListener,
        GoogleApiClient.OnConnectionFailedListener {

    private RestaurantService restaurantService;
    private UserService userService;
    private OrderService orderService;
    private String restaurantId;
    private Order currentOrder;
    private LayoutInflater inflater;

    private FloatingActionButton fab;
    private NavigationView navigationView;
    private GoogleApiClient mGoogleApiClient;
    private TabLayout tabs;
    private AppBarLayout appBar;
    private Menu menu;
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        restaurantService = ServiceFactory.getRestaurantService(MainActivity.this);
        userService = ServiceFactory.getUserService(MainActivity.this);
        orderService = ServiceFactory.getOrderService(MainActivity.this);
        restaurantId = userService.getFirstRestaurantId(Preferences.getCurrentUserEmail());

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

        fab = (FloatingActionButton) findViewById(R.id.fab);
        appBar = (AppBarLayout) findViewById(R.id.appbar);
        inflater = LayoutInflater.from(MainActivity.this);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        //noinspection deprecation
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        navigationView.getMenu().getItem(1).setChecked(true);

        setUserInfo();

        if (restaurantId != null) {
            initFragment(R.layout.content_active_orders);
            initializeActiveOrders();
            navigationView.getMenu().getItem(1).setChecked(true);
        } else {
            initFragment(R.layout.content_list_restaurants);
            initializeListRestaurants();
            navigationView.getMenu().getItem(4).setChecked(true);
        }

        Utils.setAnalyticsDate(new Date());