package com.joe.print.mvp.print;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.gingersoft.gsa.cloud.common.constans.OrderTypeConstans;
import com.gingersoft.gsa.cloud.common.core.restaurant.utils.RestaurantExpandInfoUtils;
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils;
import com.gingersoft.gsa.cloud.common.constans.ExpandConstant;
import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean;
import com.gingersoft.gsa.cloud.print.bean.PrjBean;
import com.joe.print.mvp.model.bean.HtmlLable;
import com.joe.print.mvp.print.common.HtmlContract;
import com.joe.print.R;
import com.joe.print.mvp.ui.view.KitChenPrjFoodView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.joe.print.mvp.print.common.HtmlContract.LABLE_P;

/**
 * 廚房單打印
 */
public class PrintPrjKitchen extends PrinterRoot {

    private static final String font_size_table_number = "48";
    private static final String font_size_first_order = "40";
    private static final String font_size_print_quantity = "30";
    private static final String font_size_order_num_text = "24";
    private static final String font_size_order_num = "40";
    private static final String font_size_take_code_text = "20";
    private static final String font_size_take_code = "20";

    private static final String font_size_order_time_text = "28";
    private static final String font_size_order_time = "28";
    private static final String font_size_food_time = "28";

    private static final String font_size_opening_time_text = "20";
    private static final String font_size_opening_time = "20";

    private static final String font_size_kitchen_location = "20";
    private static final String font_size_operator = "20";

    private static final String font_size_people_text = "24";
    private static final String font_size_people = "24";

    private static final String font_size_kitchen_print_table_number2 = "48";
    private static final String font_size_prj_page_index = "28";

    private int foodFontSize = 24;
    private int modifierFontSize = 24;
    private int foodIsBold;
    private int modifierIsBold;
    private int foodIsItalic;
    private int modifierIsItalic;
    private String[] languageTypes;

    private static Map<String, List<PrjBean>> prjMap;

    @Override
    public Map<String, List<Bitmap>> getPrintBitmap(Context mContext, PrinterDeviceBean deviceBean) {
        Map<String, List<Bitmap>> bitmapMaps = new HashMap<>();
        //通過打印位置生成多張用於打印的bitmap
        for (Map.Entry<String, List<PrjBean>> entry : getPrjMap().entrySet()) {
            String key = entry.getKey();
            List<Bitmap> bitmaps = new ArrayList<>();

            List<PrjBean> noCut = new ArrayList<>();
            //不帶*號，所有同樣廚房位置的食品都在一張紙上
            for (PrjBean bean : entry.getValue()) {
                if (bean.getStatus() == 2) {
                    List<PrjBean> beans = new ArrayList<>();
                    beans.add(bean);
                    Bitmap bitmap = getKitChenPrintBitmap(mContext, key, beans, deviceBean);
                    bitmaps.add(bitmap);
                } else {
                    noCut.add(bean);
                }
            }

            if (noCut.size() > 0) {
                Bitmap bitmap = getKitChenPrintBitmap(mContext, key, noCut, deviceBean);
                bitmaps.add(bitmap);
            }
            if (key == null) {
                key = "";
            }
            bitmapMaps.put(key, bitmaps);
        }
        prjMap.clear();
        return bitmapMaps;
    }

    @Override
    public String[] getPrintDatas(Context mContext, PrinterDeviceBean deviceBean) {
        if (getPrjMap().size() == 0) {
            return new String[]{"<html><body></body></html>"};
        }
        try {
            this.foodFontSize = Integer.parseInt(deviceBean.getFoodFont()) * 2;
            this.modifierFontSize = Integer.parseInt(deviceBean.getModifierFont()) * 2;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        this.foodIsBold = deviceBean.getFoodIsBold();
        this.modifierIsBold = deviceBean.getModifierIsBold();
        this.foodIsItalic = deviceBean.getFoodIsItalic();
        this.modifierIsItalic = deviceBean.getModifierIsItalic();
        this.languageTypes = deviceBean.getLanguageType().split(",");

        List<String> pritContents = new ArrayList<>();
        for (Map.Entry<String, List<PrjBean>> entry : getPrjMap().entrySet()) {
            //不帶*號，所有同樣廚房位置的食品都在一張紙上
//            for (PrjBean bean : entry.getValue()) {
            pritContents.add(getBBPosPrintData(entry.getKey(), entry.getValue(), entry.getValue().get(0)));
//            }
        }
        return (String[]) pritContents.toArray();
    }

    private String getBBPosPrintData(String key, List<PrjBean> prjBeans, PrjBean prjBean) {
        String stringBuilder = "<html><body>" +
                getHtmlHeadInfo(key, prjBean) +
                getHtmlKitchenFood(prjBeans) +
                getHtmlEndInfo(prjBean) +
                "</body></html>";
        return stringBuilder;
    }

    private String getHtmlHeadInfo(String key, PrjBean prjBean) {

        List<HtmlLable> htmlLables = new ArrayList<>();

        //台號
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, getTableName(prjBean), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_table_number)));
        //頭單標籤
        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintFirstOrder, false)) {
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, getTableName(prjBean),
                    new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_first_order),
                    new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_ALIGN, HtmlContract.value_align_center, HtmlContract.value_type_string)));
        }
        //統計打印數
        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintStatisticsAmount, false)) {
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, String.valueOf(prjBean.getQuantity()), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_print_quantity)));
        }
        //訂單碼
        if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getBillNo())) {
            htmlLables.add(new HtmlLable(getRowLableStart()));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, "訂單碼：", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_order_num_text)));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, prjBean.getBillNo(), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_order_num)));
            htmlLables.add(new HtmlLable(getRowLableEnd()));
        }
        //取餐碼
        if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getTakeFoodCode())) {
            htmlLables.add(new HtmlLable(getRowLableStart()));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, "取餐碼：", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_take_code_text)));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, prjBean.getTakeFoodCode(), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_take_code)));
            htmlLables.add(new HtmlLable(getRowLableEnd()));
        }
        //落單時間，為當前時間
        htmlLables.add(new HtmlLable(getRowLableStart()));
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, "落單時間：", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_order_time_text)));
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, TimeUtils.getCurrentTimeInString(TimeUtils.DEFAULT_DATE_MDHM), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_order_time)));
        htmlLables.add(new HtmlLable(getRowLableEnd()));
        //盡快送達
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, "盡快送達", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_food_time)));
        //開台時間
        htmlLables.add(new HtmlLable(getRowLableStart()));
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, "開檯時間：", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_opening_time_text)));
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, TimeUtils.parseTimeRepeat(prjBean.getOrderDetailsTime(), TimeUtils.DEFAULT_DATE_MDHM), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_opening_time)));
        htmlLables.add(new HtmlLable(getRowLableEnd()));
        //廚房位置
        if (!TextUtil.isEmptyOrNullOrUndefined(key) && !key.equals("-1")) {
            htmlLables.add(new HtmlLable(getRowLableStart(new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_kitchen_location))));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, key + "廚房"));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, prjBean.getUserName()));
            htmlLables.add(new HtmlLable(getRowLableEnd()));
        }
        //人數
        if (prjBean.getPerson() != 0) {
            htmlLables.add(new HtmlLable(getRowLableStart()));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, key + "人數", new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_people_text)));
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_COLUMN, String.valueOf(prjBean.getPerson()), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_people)));
            htmlLables.add(new HtmlLable(getRowLableEnd()));
        }
        htmlLables.add(new HtmlLable(LABLE_P, HtmlContract.dividing_line));
        htmlLables.add(new HtmlLable(getBrLable()));

        return getHtmlLables(htmlLables.toArray(new HtmlLable[htmlLables.size()]));
    }

    private String getHtmlKitchenFood(List<PrjBean> prjBeans) {

        setFoodItemType(prjBeans);

        List<HtmlLable> htmlLables = new ArrayList<>();

        for (PrjBean prjBean : prjBeans) {


        }

        htmlLables.add(new HtmlLable(getBrLable()));
        return getHtmlLables(htmlLables.toArray(new HtmlLable[htmlLables.size()]));
    }

    private String getHtmlEndInfo(PrjBean prjBean) {
        List<HtmlLable> htmlLables = new ArrayList<>();
        //台號
        htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, getTableName(prjBean), new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_kitchen_print_table_number2)));
        //廚房單頁碼
        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintPage, false)) {
            htmlLables.add(new HtmlLable(HtmlContract.LABLE_P, prjBean.getCurrentIndex() + "/" + prjBean.getTotalPrj(),
                    new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_FONT_SIZE, font_size_prj_page_index),
                    new HtmlLable.Attributes(HtmlContract.ATTRIBUTES_ALIGN, HtmlContract.value_align_center, HtmlContract.value_type_string)));
        }
        return getHtmlLables(htmlLables.toArray(new HtmlLable[htmlLables.size()]));
    }

    @Override
    public int getPrintCount(Context context) {
        return 1;
    }

    public Bitmap getKitChenPrintBitmap(Context context, String key, PrjBean data, PrinterDeviceBean printerDeviceBean) {
        List<PrjBean> beans = new ArrayList<>();
        beans.add(data);
        return getKitChenPrintBitmap(context, key, beans, printerDeviceBean);
    }

    /**
     * 獲取"廚房單"圖片
     *
     * @param context
     * @return
     */
    public Bitmap getKitChenPrintBitmap(Context context, String key, List<PrjBean> data, PrinterDeviceBean printerDeviceBean) {
        if (data == null || data.size() <= 0) {
            return null;
        }
        PrjBean prjBean = data.get(0);
        if (prjBean == null) {
            return null;
        }
        setFoodItemType(data);
        View view = LinearLayout.inflate(context, R.layout.print_kitchen2, null);
        TextView tvTableNumber = view.findViewById(R.id.tv_kitchen_print_table_number);
        TextView tvOrderNumberText = view.findViewById(R.id.tv_order_num_text);
        TextView tvOrderNumber = view.findViewById(R.id.tv_order_num);
        TextView tvTakeCodeText = view.findViewById(R.id.tv_take_code_text);
        TextView tvTakeCode = view.findViewById(R.id.tv_take_code);
        TextView tvTakeTime = view.findViewById(R.id.tv_food_time);
        TextView tvOpeningTime = view.findViewById(R.id.tv_opening_time);
        TextView tvOrderTime = view.findViewById(R.id.tv_order_time);
        TextView tvKitChenLocationText = view.findViewById(R.id.tv_kitchen_location_text);
        TextView tvKitChenLocation = view.findViewById(R.id.tv_kitchen_location);
        TextView tvPeople = view.findViewById(R.id.tv_people);
        TextView tvCurrentPageIndex = view.findViewById(R.id.tv_prj_page_index);
//        RecyclerView rvFood = view.findViewById(R.id.rv_kitchen_food);
        LinearLayout foodLayout = view.findViewById(R.id.ll_kitchen_food);
        TextView tvTableNumber2 = view.findViewById(R.id.tv_kitchen_print_table_number_bottom);
        TextView tvFirstOrder = view.findViewById(R.id.tv_kitchen_print_first_order);
        TextView tvPrintQuantity = view.findViewById(R.id.tv_kitchen_print_quantity);

        TextView tvOrderReserved = view.findViewById(R.id.tv_order_reserved);
        LinearLayout llWaiter = view.findViewById(R.id.ll_waiter);
        TextView tvWaiterText = view.findViewById(R.id.tv_waiter_text);
        TextView tvWaiter = view.findViewById(R.id.tv_waiter);

        LinearLayout layoutOpenTableTime = view.findViewById(R.id.ll_opening_table_time);

        foodLayout.addView(new KitChenPrjFoodView(context, data, printerDeviceBean));
//        KitChenPrjPrintFoodAdapter foodAdapter = new KitChenPrjPrintFoodAdapter(data, printerDeviceBean);
//        rvFood.setLayoutManager(new LinearLayoutManager(context));
//        rvFood.setAdapter(foodAdapter);
        //廚房位置
        if (!TextUtil.isEmptyOrNullOrUndefined(key) && !key.equals("-1")) {
            tvKitChenLocationText.setVisibility(View.VISIBLE);
            tvKitChenLocation.setText(key);
        } else {
            tvKitChenLocationText.setVisibility(View.GONE);
        }

        if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getBillNo())) {
            //訂單碼不為空
            tvOrderNumberText.setText("訂單碼:");
            tvOrderNumber.setText(prjBean.getBillNo());
        } else {
            //訂單號
            tvOrderNumber.setText(prjBean.getOrderNo());
        }
        switch (prjBean.getOrderType()) {
            case OrderTypeConstans.order_type_1:
            case OrderTypeConstans.order_type_3:
                tvTableNumber.setText("堂食");
                tvTableNumber2.setText("堂食");
                tvTableNumber.setText(prjBean.getTableName());
                tvTableNumber2.setText(prjBean.getTableName());
//                if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getTakeFoodCode())) {
//                    tvTakeCodeText.setVisibility(View.VISIBLE);
//                    tvTakeCode.setVisibility(View.VISIBLE);
//                    tvTakeCode.setText(prjBean.getTakeFoodCode());
//                }
                break;
            case OrderTypeConstans.order_type_7:
                layoutOpenTableTime.setVisibility(View.GONE);
                tvTableNumber.setText("自取");
                tvTableNumber2.setText("自取");
                if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getTakeFoodCode())) {
                    tvTakeCodeText.setVisibility(View.VISIBLE);
                    tvTakeCode.setVisibility(View.VISIBLE);
                    tvTakeCode.setText(prjBean.getTakeFoodCode());
                }
                break;
            case OrderTypeConstans.order_type_8:
                layoutOpenTableTime.setVisibility(View.GONE);
                tvTableNumber.setText("凍鏈");
                tvTableNumber2.setText("凍鏈");
                tvOrderNumberText.setText("訂單碼:");
                tvOrderNumber.setText(prjBean.getTakeFoodCode());
                break;
            default:
                layoutOpenTableTime.setVisibility(View.GONE);
                tvTableNumber.setText("外賣");
                tvTableNumber2.setText("外賣");
                tvOrderNumberText.setText("訂單碼:");
                tvOrderNumber.setText(prjBean.getTakeFoodCode());
                break;
        }
        //操作人員名稱0
        if (!TextUtils.isEmpty(prjBean.getUserName())) {
            tvWaiter.setText(prjBean.getUserName());
        } else {
            tvWaiter.setText(prjBean.getMemberName());
        }
//        if (TextUtil.isEmptyOrNullOrUndefined(prjBean.getTableName())) {
//            layoutOpenTableTime.setVisibility(View.GONE);
//            switch (prjBean.getOrderType()) {
//                case 1:
//                case 3:
//                    tvTableNumber.setText("堂食");
//                    tvTableNumber2.setText("堂食");
//                    if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getTakeFoodCode())) {
//                        tvTakeCodeText.setVisibility(View.VISIBLE);
//                        tvTakeCode.setVisibility(View.VISIBLE);
//                        tvTakeCode.setText(prjBean.getTakeFoodCode());
//                    }
//                    break;
//                case 7:
//                    tvTableNumber.setText("自取");
//                    tvTableNumber2.setText("自取");
//                    if (!TextUtil.isEmptyOrNullOrUndefined(prjBean.getTakeFoodCode())) {
//                        tvTakeCodeText.setVisibility(View.VISIBLE);
//                        tvTakeCode.setVisibility(View.VISIBLE);
//                        tvTakeCode.setText(prjBean.getTakeFoodCode());
//                    }
//                    break;
//                default:
//                    tvTableNumber.setText("外賣");
//                    tvTableNumber2.setText("外賣");
//                    tvOrderNumberText.setText("訂單碼：");
//                    tvOrderNumber.setText(prjBean.getTakeFoodCode());
//                    break;
//            }
//        } else {
//            tvTableNumber.setText(prjBean.getTableName());
//            tvTableNumber2.setText(prjBean.getTableName());
//        }
        //人數
        if (prjBean.getPerson() != 0) {
            tvPeople.setText(prjBean.getPerson() + "");
            view.findViewById(R.id.tv_people_text).setVisibility(View.VISIBLE);
            view.findViewById(R.id.tv_people).setVisibility(View.VISIBLE);
        }
        if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getTakeTime())) {
            tvTakeTime.setText("取餐:" + prjBean.getTakeTime());
        } else if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getSendTime())) {
            tvTakeTime.setText("送達:" + prjBean.getSendTime());
        } else {
            tvTakeTime.setVisibility(View.GONE);
        }
        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintFirstOrder, false)) {
            tvFirstOrder.setText("<頭單>");
            tvFirstOrder.setVisibility(prjBean.getIsFirstSendOrder() == 1 ? View.VISIBLE : View.GONE);
        } else {
            tvFirstOrder.setVisibility(View.GONE);
        }

        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintStatisticsAmount, false)) {
            tvPrintQuantity.setText(prjBean.getQuantity() + "");
        } else {
            tvPrintQuantity.setVisibility(View.GONE);
        }
        //開台時間
        tvOpeningTime.setText(TimeUtils.parseTimeRepeat(prjBean.getOrderDetailsTime(), TimeUtils.DEFAULT_DATE_MDHM));

//        if (OpenTableManage.getDefault().getTableBean() != null) {
//            //台號
//            tvTableNumber.setText(prjBean.getTableName());
//            tvTableNumber2.setText(prjBean.getTableName());
//            //人數
//            tvPeople.setText(prjBean.getPerson() + "");
//            //訂單號
//            tvOrderNumber.setText(prjBean.getOrderNo());
//            //開台時間
//            tvOpeningTime.setText(TimeUtils.parseTimeRepeat(prjBean.getOrderDetailsTime(), TimeUtils.DEFAULT_DATE_FORMAT));
//        }
        //落單時間，為當前時間
        tvOrderTime.setText(TimeUtils.getCurrentTimeInString(TimeUtils.DEFAULT_DATE_MDHM));
        if (RestaurantExpandInfoUtils.getValue(ExpandConstant.PrintPage, false)) {
            if (prjBean.getCurrentIndex() <= prjBean.getTotalPrj()) {
                tvCurrentPageIndex.setText(prjBean.getCurrentIndex() + "/" + prjBean.getTotalPrj());
            }
        }

        return viewToZoomBitmap(context, view, printerDeviceBean);
    }

    private String getOrderNumTextByOrdeType(int orderType) {
        switch (orderType) {
            case 1:
            case 3:
                return "單號";//堂食
            case 7:
                return "訂單碼";//自取
            default:
                return "訂單碼";//外送
        }
    }


    private void setFoodItemType(List<PrjBean> data) {
        for (PrjBean bean : data) {
            if (bean.getParentId() == 0) {
                //沒有父級id，則是第一級食品
                bean.setItemType(1);
            }
            //如果父級id不為0，是細項
            if (bean.getParentId() != 0) {
                bean.setItemType(2);//先設置為細項，再通過下面的遍歷確定是否是第三級細項
                //循環遍歷查找父級食品
                for (PrjBean itembean : data) {
                    if (bean.getParentId() == itembean.getOrderDetailsId()) {
                        //如果父級是細項，則當前食品就是二級細項
                        bean.setItemType(bean.getItemType() + 1);
                        break;
                    }
                }
            }
        }
    }

    private String getTableName(PrjBean prjBean) {
        if (TextUtil.isEmptyOrNullOrUndefined(prjBean.getTableName())) {
            switch (prjBean.getOrderType()) {
                case 1:
                case 3:
                    return "堂食";
                case 7:
                    return "自取";
                default:
                    return "外賣";
            }
        } else {
            return prjBean.getTableName();
        }
    }

//    private String getProductNameByLanguageType(PrjBean prjBean) {
//        for (String type : languageTypes) {
//            String languageType = type;
//            if (languageType.contains(".")) {
//                languageType = type.substring(0, type.indexOf("."));
//            }
//            if (languageType.equals("2")) {
//                //語言二
//                if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getProductName2())) {
//                    return prjBean.getProductName2();
//                }
//            } else if (languageType.equals("3")) {
//                //語言三
//                if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getProductName3())) {
//                    return prjBean.getProductName3();
//                }
//            } else {
//                //語言一或其他
//                if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getProductName())) {
//                    return prjBean.getProductName();
//                }
//            }
//        }
//    }

    public static Map<String, List<PrjBean>> getPrjMap() {
        if (prjMap == null) {
            prjMap = new HashMap<>();
        }
        return prjMap;
    }
}
