import {talkEvent} from "http://talk.kospo.co.kr:3000/static/js/module/talkEvent.js";
import {global} from "http://talk.kospo.co.kr:3000/static/js/module/variable.js";
import Common from "http://talk.kospo.co.kr:3000/static/js/utils.js";

// 첨부파일 업로드 기능

function readFileAsDataURL(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (e) => resolve(e.target.result);
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

function loadImage(src) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = reject;
        img.src = src;
    });
}

const attachUpload = async (files) => {
    checkAllowExt()
    const chunkSize = 256 * 1024;
    const key = talkEvent.generateUUID()

    const workId = localStorage.getItem('workId');
    const workNm = localStorage.getItem('workNm');
    const talkId = localStorage.getItem(global.tabId);

    if(talkId === null || workId === null) {
        global.notifier.alert('통신 오류가 발생 했어요.<br/>새로고침 해주세요.')
        return
    }

    const $files = [];
    const insDate = Common.dateWithNanos(new Date());
    let allFileSize = 0;
    let isImage = true;

    // mimtype 조회 이미지가 아닌 다른 파일이 있는지 확인
    Array.from(files).forEach((fi) => {
        if (!(fi.type.includes('image'))) {
            isImage = false;
        }
    })

    for (const file of Array.from(files)) {
        const idx = Array.from(files).indexOf(file);
        allFileSize += file.size;
        const att = {
            onm: file.name,
            type: file.type,
            sort: idx,
            size: file.size,
        }

        // 파일 전체가 이미지 일 경우 해당 바이너리 정보 주입
        if (isImage) {
            // 1. 파일을 읽어서 DataURL로 변환 (FileReader 비동기 처리)
            const dataURL = await readFileAsDataURL(file);
            // 2. 변환된 DataURL을 이용해 이미지 로드 (Image 비동기 처리)
            const img = await loadImage(dataURL);
            // 3. 썸네일 용 dataURL 생성
            const blob = await Common.cropImage(img, 105);
            att.data = blob;
        }

        $files.push(att);

    }
    /*
    첨부파일 업로드 설정 소켓 통신으로 해당 파일의 정보를 보내준다.
    정보를 받는 대상자는 첨부파일 업로드 화면을 렌더링 한다.
    이미지 같은 경우는 위 바이너리 정보로 썸네일 구성
    이미지외 파일 혼합된 경우 파일 다운로드 화면 구성
    (서버에서는 해당 내용으로 메시지를 저장한다.)
    */
    talkEvent.attach(global.talkParams({
        type: 'INIT',
        talkId: talkId,
        workId: workId,
        workNm: workNm,
        message: isImage ? "[사진]" : '[파일]',
        insDate: insDate,
        talkAttachDtos: $files,
        attach: {
            key: key,
            totalSize: allFileSize
        }
    }))


    setTimeout(attachStart, 300)

    function checkAllowExt() {
        const allow = ["jpg", "jpeg", "gif", "png", "bmp",
            "xls", "xlsx", "csv", "pdf", "hwp", "doc", "docx", "ppt", "pptx", "txt",
            "zip", "egg",
            "mp4"]

        files = Array.from(files).filter((file) => {
            const fileExt = file.name.toLowerCase().substr(file.name.toLowerCase().lastIndexOf('.') + 1)
            return allow.join(',').includes(fileExt)
        })
    }

    function attachStart() {
        if (files.length !== 0) {
            Array.from(files).forEach((file, idx) => {
                const vnm = Common.getAttachVnm(new Date(), global.tabId)
                console.log(idx, vnm)
                let offset = 0;
                /*
                각파일 정보를 전송
                 (서버에서는 메시지 첨부파일을 저장한다.)
                */
                talkEvent.attach(global.talkParams({
                    type: 'START',
                    talkId: talkId,
                    workId: workId,
                    workNm: workNm,
                    insDate: insDate,
                    attach: {
                        key: key,
                        onm: file.name,
                        vnm: vnm,
                        size: file.size,
                        type: file.type,
                        sort: idx,
                        totalSize: allFileSize

                    }
                }))
                readAndSEndChunk(file, idx, offset, vnm)
            })
        }

    }

    let progressSize = 0;

    function readAndSEndChunk(file, idx, offset, vnm) {
        const reader = new FileReader();
        reader.onload = (e) => {
            const chunk = reader.result;
            /*
            파일의 바이너리 정보를 chunkSize 256kb 로 잘라서 전송한다.
            받는 대상자는 해당 첨부파일의 진행률을 돌려받는다.
            */
            talkEvent.attach(global.talkParams({
                type: 'PROGRESS',
                talkId: talkId,
                workId: workId,
                workNm: workNm,
                insDate: insDate,
                attach: {
                    key: key,
                    onm: file.name,
                    sort: idx,
                    vnm: vnm,
                    totalSize: allFileSize,
                    size: progressSize,
                    data: Array.from(new Uint8Array(chunk))
                },
            }))

            progressSize += chunk.byteLength;
            offset += chunk.byteLength;
            if (offset < file.size) {
                Common.sleep(100).then(() => {
                    readAndSEndChunk(file, idx, offset, vnm)
                })
            } else {
                /*
                파일 전송 완료 메시지
                */
                talkEvent.attach(global.talkParams({
                    type: 'END',
                    talkId: talkId,
                    workId: workId,
                    workNm: workNm,
                    insDate: insDate,
                    attach: {
                        onm: file.name,
                        vnm: vnm,
                        key: key,
                    },
                }))
            }
        }

        const slice = file.slice(offset, offset + chunkSize);
        reader.readAsArrayBuffer(slice)
    }
}

export {attachUpload}