package com.its.op.service.its.vms;

import com.its.op.entity.its.vms.*;
import com.its.op.global.VmsIfscManager;
import com.its.op.global.VmsManager;
import com.its.op.dto.its.vms.*;
import com.its.op.dao.repository.its.vms.TbVmsCtlrRepository;
import com.its.op.dao.repository.its.vms.TbVmsDsplSchRepository;
import com.its.utils.ItsUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.sanselan.Sanselan;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class TbVmsDsplSchService {

    private final TbVmsDsplSchRepository repo;
    private final TbVmsCtlrRepository vmsRepo;
    private final TbVmsFormService formService;

    // 데이터 1건 조회, 없으면 exception
    private TbVmsDsplSch requireOne(TbVmsDsplSchKey id) throws NoSuchElementException {
        Optional<TbVmsDsplSch> info = this.repo.findById(id);
        if (info.isPresent()) {
            return info.get();
        }
        else {
            throw new NoSuchElementException("데이터가 존재하지 않습니다: " + id);
        }
//        return repo.findById(id)
//                .orElseThrow(() -> new NoSuchElementException("데이터가 존재하지 않습니다: " + id));
    }

    // 전체 데이터 조회
    @Transactional(readOnly = true)
    public List<TbVmsDsplSchDto> findAll() {
        List<TbVmsDsplSchDto> result = new ArrayList<>();
        List<TbVmsDsplSch> data = this.repo.findAll();
        data.forEach(obj -> {
            result.add(obj.toDto());
//            if (!("5").equals(obj.getTrfcSituTypeCd()) &&
//                !("6").equals(obj.getTrfcSituTypeCd())) {
//                result.add(obj.toDto());
//            }
        });
        return result;
    }

    // 데이터 변경 또는 생성-개별(데이터가 존재하면 업데이트 없으면 신규로 생성)
    @Transactional
    public TbVmsDsplSchDto mergeInfo(TbVmsDsplSchDto.TbVmsDsplSchUpdReq req) {
        TbVmsDsplSch obj = req.toEntity();
        this.repo.save(obj);
        return obj.toDto();
    }

    /**
     * VMS 폼 표출 스케줄 조회
     * @param id
     * @param vmsSchType
     * @param vmsSchFormType
     * @return
     */
    public List<TbVmsDsplSchDto> findAllVmsDsplSchedule(Long id, String vmsSchType, List<Integer> vmsSchFormType) {
        List<TbVmsDsplSchDto> result = new ArrayList<>();
        List<TbVmsDsplSch> data = this.repo.findAllByVmsCtrlTrfcSituTypeCd(id, vmsSchType, vmsSchFormType);
        data.forEach(obj -> {
            result.add(obj.toDto());
        });
        return result;
    }

    private Color getColor(int code) {
        if (code == 0) return Color.BLACK;
        if (code == 1) return Color.RED;
        if (code == 2) return Color.GREEN;
        if (code == 3) return Color.YELLOW;
        return Color.BLACK;
    }

    /**
     * VMS 교통정보 폼을 실시간 으로 그린다.
     * @param vms
     * @param dto
     * @param formObjs
     * @return
     * @throws IOException
     */
    private byte[] createVmsTrafScheForm(TbVmsCtlr vms, TbVmsDsplSchDto dto, List<TbVmsFormObjectDetlDto> formObjs, VmsFormDrawTrafDto.VmsFormDrawTrafReq req) throws IOException {

        Integer phase = 0;
        String imagFmt = "png";
        if (vms == null || vms.getType() == null) {
            log.error("Not Found VMS Controller: {}", vms);
            return dto.getVmsFormImag();
        }
        if (formObjs.size() == 0) {
            log.error("VMS Objects zero: {}", vms);
            return dto.getVmsFormImag();
        }

        Long[] ifscIds = new Long[4];
        if (dto != null) {
            phase = dto.getPhase();
            ifscIds[0] = dto.getFrstVmsIfscId();
            ifscIds[1] = dto.getSecdVmsIfscId();
            ifscIds[2] = dto.getThirVmsIfscId();
            ifscIds[3] = dto.getFourVmsIfscId();
        } else if (req != null) {
            ifscIds[0] = req.getFrstVmsIfscId();
            ifscIds[1] = req.getSecdVmsIfscId();
            ifscIds[2] = req.getThirVmsIfscId();
            ifscIds[3] = req.getFourVmsIfscId();
        } else {
            log.error("VMS Form draw request object error");
            return null;
        }
        int formColorCd = formObjs.get(0).getVmsFormColrCd();
        /**
         * 배경 이미지를 만든다.
         */
        int width = vms.getType().getVmsWdth();
        int height = vms.getType().getVmsHght();
        // TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
        BufferedImage formImage = new BufferedImage(width, height, (("png").equals(imagFmt) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB));
        Graphics2D g2d = (Graphics2D)formImage.createGraphics();  //createGraphics();getGraphics();
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(getColor(formColorCd));
        g2d.fillRect(0, 0, width, height);

        formObjs.forEach(obj -> {
            int objKind;
            String dsplText = obj.getVmsDsplTxt();
            int objType = obj.getVmsFormObjectTypeCd();
            if (objType ==  1 || //이미지 심볼
                objType ==  2 || //소통정보이미지
                objType ==  3 || //파일이미지
                objType == 17 || //소통이미지1
                objType == 27 || //소통이미지2
                objType == 37 || //소통이미지3
                objType == 47 )  //소통이미지4
            {
                if (objType == 1) objKind = 1;  //Image Id
                else              objKind = 2;  //Image
            }
            else {
                objKind = 0;  //문자열그리기
            }

            Long ifscId = null;
            if (objType >= 11 && objType < 17)
                ifscId = ifscIds[0];
            else
            if (objType >= 21 && objType < 27)
                ifscId = ifscIds[1];
            else
            if (objType >= 31 && objType < 37)
                ifscId = ifscIds[2];
            else
            if (objType >= 41 && objType < 47)
                ifscId = ifscIds[3];

            if (ifscId != null && ifscId != 0) {
                TbVmsIfsc vmsIfsc = VmsIfscManager.get(ifscId);
                if (vmsIfsc != null) {
                    switch(objType)
                    {
                        case 11: case 21: case 31: case 41:
                        dsplText = vmsIfsc.getVmsIfscNm();
                        break;
                        case 12: case 22: case 32: case 42:
                        dsplText = vmsIfsc.getDsplStrtNodeNm();
                        break;
                        case 13: case 23: case 33: case 43:
                        dsplText = vmsIfsc.getDsplEndNodeNm();
                        break;
                    }
                }
            }

            // 그리기 시작한다
            int left = obj.getVmsDsplXcrdn();
            int top = obj.getVmsDsplYcrdn();
            if (objKind == 0) {
                // 문자열 그리기
                int fontSize  = obj.getVmsFontSize();
                int fontStyle = (obj.getVmsFontBold() == 1) ? Font.BOLD : Font.PLAIN;
                int dsplWidth = obj.getVmsDsplWidth();

                Font txtFont = new Font(obj.getVmsFontName(), fontStyle, fontSize);
                txtFont = txtFont.deriveFont(fontSize * 1.35f);
                g2d.setFont(txtFont);
                FontMetrics fm = g2d.getFontMetrics(txtFont);
                int txtWidth = fm.stringWidth(dsplText);
                int nWidth = dsplWidth - txtWidth;
                if (obj.getVmsFontAlign() == 1) {
                    // right, 좌측에서 글자길이를 뺀다음 만약 음수이면 0으로 설정
                    left += nWidth;
                    //left = (left + dsplWidth) - txtWidth;
                }
                else if (obj.getVmsFontAlign() == 2) {
                    // center, 원래 글자의 중앙값을 얻은 다음에 조정된 글자의 1/2 크기를 뺀다음 음수이면 0으로 설정
                    left += (nWidth / 2);
                    //left = (left + (dsplWidth / 2)) - (txtWidth/2);
                }
                if (left < 0) {
                    left = 0;
                }
                g2d.setColor(getColor(obj.getVmsFontColrCd()));
                g2d.drawString(dsplText, left, top + fm.getAscent());//fm.getHeight() - fm.getDescent() - fm.getLeading());
            }
            else {
                try {
                    BufferedImage symbol = null;
                    if (obj.getVmsDsplFigr() != null) {
                        symbol = Sanselan.getBufferedImage(obj.getVmsDsplFigr());
                    } else {
                        symbol = Sanselan.getBufferedImage(obj.getImagData());
                    }
                    g2d.drawImage(symbol, left, top, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        //String saveDir = ItsUtils.createUserDir("/image/vms/traf-sche/");
        //ItsUtils.saveImageFile(formImage, imagFmt, saveDir + vms.getVmsCtlrNmbr() + "_" + phase + "." + imagFmt);
        //log.info("{}", saveDir + vms.getVmsCtlrNmbr() + "_" + phase + "." + imagFmt);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(formImage, imagFmt, out);
        g2d.dispose();
        return out.toByteArray();
    }

    /**
     * VMS 교통정보 폼 실시간 드로잉
     * @param id
     * @param formId
     * @param req
     * @return
     */
    public VmsFormDrawTrafDto drawTrafficForm(Long id, Integer formId, VmsFormDrawTrafDto.VmsFormDrawTrafReq req) {
        VmsFormDrawTrafDto result = VmsFormDrawTrafDto.builder()
                .vmsFormId(formId)
                .vmsFormImag(null)
                .imagFmt("png").build();

        // 교통정보 스케쥴인 경우 교통정보 폼을 만들어서 리턴해 준다.
        TbVmsCtlr obj = VmsManager.get(id);
        if (obj == null) {
            return result;
        }
        List<TbVmsFormObjectDetlDto> formObjs = this.formService.findByVmsFormObject(formId);
        try {
            // 교통정보 폼 그리기
            result.setVmsFormImag(createVmsTrafScheForm(obj, null, formObjs, req));
        } catch (IOException e) {
            log.error("{}", e.getMessage());
        }

        return result;
    }
    /**
     * 자동 스케줄 목록 조회
     * @param id
     * @return
     */
    public List<TbVmsDsplSchDto> findAllVmsDsplSchedule(Long id) {
        //List<Integer> trfcSituTypeCd = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> trfcSituTypeCd = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<TbVmsDsplSchDto> trfSchList = findAllTraffic(id);
        List<TbVmsDsplSchDto> etcSchList = findAllVmsDsplSchedule(id, "A", trfcSituTypeCd);
        trfSchList.addAll(etcSchList);
        return trfSchList;
    }
    // 교통정보
    public List<TbVmsDsplSchDto> findAllTraffic(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(0);
        List<TbVmsDsplSchDto> dtoList = findAllVmsDsplSchedule(id, "A", formTypeCd);

        // 교통정보 스케쥴인 경우 교통정보 폼을 만들어서 리턴해 준다.
        TbVmsCtlr obj = VmsManager.get(id);
        if (obj == null) {
            return dtoList;
        }
        dtoList.forEach(dto -> {
            List<TbVmsFormObjectDetlDto> formObjs = this.formService.findByVmsFormObject(dto.getVmsFormId());
            try {
                // 교통정보 폼 그리기
                dto.setVmsFormImag(createVmsTrafScheForm(obj, dto, formObjs, null));
            } catch (IOException e) {
                log.error("{}", e.getMessage());
            }
        });
        return dtoList;
    }

    // 정체
    public List<TbVmsDsplSchDto> findAllCongest(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(5);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }
    // 돌발
    public List<TbVmsDsplSchDto> findAllIncident(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(1);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }
    // 공사/행사
    public List<TbVmsDsplSchDto> findAllEvent(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(2);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }
    // 홍보
    public List<TbVmsDsplSchDto> findAllHongbo(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(3);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }
    // 우회도로
    public List<TbVmsDsplSchDto> findAllDetour(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(4);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }
    // 재난안전
    public List<TbVmsDsplSchDto> findAllSafety(Long id) {
        List<Integer> formTypeCd = Collections.singletonList(6);
        return findAllVmsDsplSchedule(id, "A", formTypeCd);
    }

    /**
     * 기본 스케줄 목록 조회
     * @param id
     * @return
     */
    public List<TbVmsDsplSchDto> findAllDefault(Long id) {
        List<Integer> trfcSituTypeCd = Collections.singletonList(3);
        return findAllVmsDsplSchedule(id, "B", trfcSituTypeCd);
    }

    /**
     * 고정 스케줄 목록 조회(홍보폼)
     * @param id
     * @return
     */
    public List<TbVmsDsplSchDto> findAllFixed(Long id) {
        List<Integer> trfcSituTypeCd = Collections.singletonList(3);
        return findAllVmsDsplSchedule(id, "F", trfcSituTypeCd);
    }

    /**
     * VMS 폼 표출 스케줄 일괄 등록(전체 VMS 편집 - 저장)
     * 기존 데이터 삭제(DELETE)
     * 요청 데이터 저장(INSERT)
     * @param id
     * @param reqList
     * @return
     */
    @Transactional
    public List<TbVmsDsplSchDto> mergeInfoList(Long id, List<TbVmsDsplSchDto.TbVmsDsplSchUpdReq> reqList) {
        List<TbVmsDsplSchDto> result = new ArrayList<>();

        HashSet<String> vmsSchTypeList = new HashSet<>();
        HashSet<Integer> vmsSchFormTypeList = new HashSet<>();
        reqList.forEach(obj -> {
            // 제어기 ID를 모두 동일하게 설정
            if (!Objects.equals(id, obj.getVmsCtlrNmbr())) {
                //log.error("VmsCtlrNmbr different: {}, {}", id, obj.getVmsCtlrNmbr());
                obj.setVmsCtlrNmbr(id);
            }
            vmsSchTypeList.add(obj.getVmsSchType());
            vmsSchFormTypeList.add(obj.getVmsSchFormType());
        });

        /**
         * 기존 데이터를 모두 삭제
         */
        List<String> vmsSchTypeCd = new ArrayList<>(vmsSchTypeList);
        List<Integer> vmsSchFormTypeCd = new ArrayList<>(vmsSchFormTypeList);
        this.repo.deleteDataByVmsCtrlTrfcSituTypeCd(id, vmsSchTypeCd, vmsSchFormTypeCd);

        /**
         * 요청 데이터 저장
         */
        for (TbVmsDsplSchDto.TbVmsDsplSchUpdReq req : reqList) {
            TbVmsDsplSch obj = req.toEntity();
//            if ("8".equals(req.getTrfcSituTypeCd())) {
//                // 재난 안전 폼 인 경우 제어기당 하나만 존재해야 한다.
//                obj.setPhase(1);
//            }
            this.repo.save(obj);    // INSERT
            result.add(obj.toDto());
        }
        return result;
    }

    /**
     * VMS 폼 표출 스케줄 일괄 등록(전체 VMS 등록 - 저장)
     * 신규 데이터를 저장한다.(INSERT only)
     * PHASE 번호를 증가 시켜야 한다. 재난안전은 스케줄당 1개가 존재해야 하므로 기존것에 덮어 저장한다(UPDATE)
     * @param reqList
     * @return
     */
    @Transactional
    public List<TbVmsDsplSchDto> batchCreateInfoList(List<TbVmsDsplSchDto.TbVmsDsplSchEditUpdReq> reqList) {
        List<TbVmsDsplSchDto> result = new ArrayList<>();
        for (TbVmsDsplSchDto.TbVmsDsplSchEditUpdReq req : reqList) {
            TbVmsDsplSch obj = req.toEntity();
//            if ("8".equals(req.getTrfcSituTypeCd())) {
//                // 재난 안전 폼 인 경우 제어기당 하나만 존재해야 한다.
//                obj.setPhase(1);
//            }
//            else {
                // 재난 안전 폼이 아닌경우 해당 폼 유형에서 최대 PHASE 로 설정 한다.
                int maxPhase = this.repo.findMaxPhaseByVmsSchType(req.getVmsCtlrNmbr(), req.getVmsSchType());
                obj.setPhase(maxPhase);
//            }
            this.repo.save(obj);    // INSERT only
            result.add(obj.toDto());
        }
        return result;
    }

    /**
     * VMS 폼 표출 스케줄 일괄 등록(전체 VMS 편집 - 저장)
     * 데이터를 저장한다.(INSERT or UPDATE)
     * @param reqList
     * @return
     */
    @Transactional
    public List<TbVmsDsplSchDto> batchMergeInfoList(List<TbVmsDsplSchDto.TbVmsDsplSchEditUpdReq> reqList) {
        List<TbVmsDsplSchDto> result = new ArrayList<>();
        for (TbVmsDsplSchDto.TbVmsDsplSchEditUpdReq req : reqList) {
            TbVmsDsplSchKey key = new TbVmsDsplSchKey(req.getVmsCtlrNmbr(), req.getVmsSchType(), req.getVmsSchFormType(), req.getPhase());
            try {
                TbVmsDsplSch obj = requireOne(key);
                obj.setEditInfo(req);
//                if ("8".equals(req.getTrfcSituTypeCd())) {
//                    // 재난 안전 폼 인 경우 제어기당 하나만 존재해야 한다.
//                    obj.setPhase(1);
//                }
                this.repo.save(obj);    // INSERT or UPDATE
                result.add(obj.toDto());
            }
            catch (Exception e) {
                log.error("batchMergeInfoList: Not Found, {}", key.toString());
            }
        }
        return result;
    }

    /**
     * 스케쥴 정보 일괄삭제(전체 VMS 편집 - 삭제)
     * @param ids
     * @return
     */
    @Transactional
    public List<TbVmsDsplSchDto.TbVmsDsplSchDelReq> batchDeleteByIds(List<TbVmsDsplSchDto.TbVmsDsplSchDelReq> ids) {
        List<TbVmsDsplSchDto.TbVmsDsplSchDelReq> result = new ArrayList<>();
        ids.forEach(obj -> {
            //TODO, VMS 폼 아이디 추가여부 확인 필요함
            TbVmsDsplSchKey key = new TbVmsDsplSchKey(obj.getVmsCtlrNmbr(), obj.getVmsSchType(), obj.getVmsSchFormType(), obj.getPhase());
            try {
                this.repo.deleteById(key);
                result.add(obj);
            }
            catch (Exception e) {
                log.error("Not Found: {}", key);
            }
        });
        return result;
    }

    /**
     * VMS 일괄 편집 시 VMS 목록 조회
     * @param vmsSizeType
     * @param vmsSchType
     * @param vmsSchFormType
     * @param vmsFormId
     * @param isEdit
     * @return
     */
    public List<TbVmsDsplSchVmsListDto> findAllByAllEditVmsList(String vmsSizeType, String vmsSchType, Integer vmsSchFormType, Integer vmsFormId, boolean isEdit) {
        List<TbVmsDsplSchVmsListDto> result = new ArrayList<>();

        Map<Long, TbVmsCtlr> vmsMap = new HashMap<>();
        List<TbVmsCtlr> vmsList = this.vmsRepo.findAllListByTypeCd(vmsSizeType);
        if (vmsList.size() == 0) {
            log.error("Not found VMS Size Type Data: {}", vmsSizeType);
            return result;
        }

        vmsList.forEach(obj -> {
            vmsMap.put(obj.getVmsCtlrNmbr(), obj);
        });
        //Map<Long, TbVmsCtlr> vmsList = vmsList.stream().collect(Collectors.toMap(TbVmsCtlr::getVmsCtlrNmbr, Function.identity()));

        Set<Long> schSet = new HashSet<>();
        List<TbVmsDsplSch> data = this.repo.findAllByAllEditVmsList(vmsSchType, vmsSchFormType, vmsFormId);
        data.forEach(obj -> {
            TbVmsDsplSchVmsListDto dto = obj.toVmsListDto();
            //log.error("EDT: {}", obj.getVmsCtlrNmbr());
            schSet.add(dto.getVmsCtlrNmbr());
            dto.setVmsInfo(vmsMap.get(dto.getVmsCtlrNmbr()), isEdit);
            result.add(dto);
        });

        if (!isEdit) {
            /** 일괄 등록 인 경우 스케줄에 등록되지 않은 VMS 를 추가해 준다. **/
            vmsList.forEach(obj -> {
                if (schSet.add(obj.getVmsCtlrNmbr())) {
                    log.error("ADD: {}", obj.getVmsCtlrNmbr());
                    /** 등록되어 있지 않음 VMS 임 **/
                    TbVmsDsplSchVmsListDto dto = TbVmsDsplSchVmsListDto.builder()
                            .vmsCtlrNmbr(obj.getVmsCtlrNmbr())
                            .vmsSchType(vmsSchType)
                            .vmsSchFormType(vmsSchFormType)
                            .phase(1)
                            .vmsFormId(vmsFormId)
                            .dsplHh(4)
                            .dsplStrtHh(ItsUtils.getSysTime())
                            .dsplEndHh("20991231235959")
                            .useYn("Y")
                            .vmsCtlrId(obj.getVmsCtlrId())
                            .vmsNm(obj.getVmsNm())
                            .selectYn("Y")
                            .build();
                    result.add(dto);
                }
            });
        }
        return result;
    }

    /**
     * VMS 교통정보 스케쥴 폼 의 정보제공구간 정보 조회
     * @param id
     * @param vmsSchType
     * @param vmsSchFormType
     * @param phase
     * @return
     */
    public VmsFormIfscDto findAllVmsFormIfsc(Long id, String vmsSchType, Integer vmsSchFormType, Integer phase) {
        VmsFormIfscDto result = VmsFormIfscDto.builder()
                .vmsCtlrNmbr(id)
                .vmsSchType(vmsSchType)
                .vmsSchFormType(vmsSchFormType)
                .phase(phase)
                .build();
        TbVmsDsplSch data = this.repo.findScheduleForm(id, vmsSchType, vmsSchFormType, phase);
        if (data != null) {
            result.setVmsFormId(data.getVmsFormId());
            if (data.getForm() != null) {
                result.setVmsFormTypeCd(data.getForm().getVmsFormTypeCd());
            }
            result.setFrstVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFrstVmsIfscId())));
            result.setSecdVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getSecdVmsIfscId())));
            result.setThirVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getThirVmsIfscId())));
            result.setFourVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFourVmsIfscId())));
            result.setFrstImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFrstImgIfscId())));
            result.setSecdImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getSecdImgIfscId())));
            result.setThirImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getThirImgIfscId())));
            result.setFourImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFourImgIfscId())));
        }
        return result;
    }
}
