(function () {

    const MAX_NUMBER_LENGTH = 16;
    let lastInputTime = 0;
    const IS_TOUCH = ("ontouchstart" in window || navigator.maxTouchPoints > 0);
    const INPUT_EVENT = IS_TOUCH ? "touchstart" : "click";

    var search_pageinsize = 20;
    var search_offset = 0;
    var search_lock = false;
    let pressTimer;

    // 번호 포맷
    function formatPhone(number) {
        if (!number) return "";
        if (number.includes("-")) return number;
        const d = number.replace(/\D/g, "");
        if (d.length === 11) return d.replace(/(\d{3})(\d{4})(\d{4})/, "$1-$2-$3");
        if (d.length === 10) return d.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
        return number;
    }

    function createPreviewItem() {
        return $(`
            <a href="javascript:" class="apx_unit" data-user-id="" data-phone="">
            <div class="thumb"></div>
            <div class="who">
                <div class="name"></div>
                <div class="num"><u class="key"></u></div>
            </div>
            </a>
        `);
    }

    function createSearchListItem() {
        return $(`
            <li>
            <a href="javascript:" data-user-id="" data-phone="">
                <div class="thumb"></div>
                <div class="who">
                <div class="name"></div>
                <div class="num"></div>
                </div>
            </a>
            </li>
        `);
    }

    // 연락처에서 번호 선택
    function pickPhone(contact, query) {
        if (!contact || !Array.isArray(contact.phoneNumbers) || contact.phoneNumbers.length === 0) {
            return null;
        }
        const q = (query ?? "").replace(/\D/g, "");
        let chosen = null;

        if (q) {
            chosen = contact.phoneNumbers.find(p => (p.normalizedNumber ?? "").includes(q));
        }
        if (!chosen) chosen = contact.phoneNumbers[0];

        const normalized = chosen?.normalizedNumber ?? "";
        let afterKey = normalized;
        if (q) {
            const idx = normalized.indexOf(q);
            if (idx >= 0) afterKey = normalized.slice(idx + q.length);
        }
        return {
            normalized,
            display: chosen?.display ?? formatPhone(normalized),
            displayAfterKey: afterKey
        };
    }

    // apx 미리보기 렌더
    function renderPreview(results, query) {
        const $preview = $("#apx_preview");
        const $more = $("#apx_more_button");

        $preview.find(".apx_unit").remove();

        if (!Array.isArray(results) || results.length === 0) {
            $preview.addClass("is-empty");
            $more.attr("data-total", "0").text("0").hide();
            return;
        }

        const first = results[0];
        const phone = pickPhone(first, query) || {};

        const $item = createPreviewItem();
        $item.attr("data-user-id", first.userId ?? "");
        $item.attr("data-phone", phone.normalized ?? "");

        if (first.thumbUrl) {
            $item.find(".thumb").css("background-image", `url('${first.thumbUrl}')`);
        } else {
            $item.find(".thumb").removeAttr("style");
        }

        $item.find(".name").text(first.name ?? "");

        const normalized = String(phone.normalized || "").replace(/\D/g, "");
        const q = String(query || "").replace(/\D/g, "");
        const $num = $item.find(".num").empty();

        if (q && normalized) {
            const idx = normalized.indexOf(q);
            if (idx >= 0) {
                $num.append(document.createTextNode(normalized.slice(0, idx)));
                $num.append($("<u/>", { "class": "key", text: q }));
                $num.append(document.createTextNode(normalized.slice(idx + q.length)));
            } else {
                $num.text(phone.display || normalized);
            }
        } else {
            $num.text(phone.display || normalized);
        }

        $preview.prepend($item).removeClass("is-empty");

        $more
            .attr("data-total", String(results.length))
            .text(String(results.length))
            .toggle(results.length >= 2);
    }

    // 전체 검색 리스트 렌더
    function renderSearchList(results) {
        var $list = $("#search_result_list");
        $list.empty();
        if (!Array.isArray(results) || results.length === 0) return;

        search_offset = 0;             
        search_lock = false;          
        $list.scrollTop(0);     

        // 첫 페이지 렌더
        renderSearchListPage(results, search_offset);

        // 스크롤 바인딩(중복 방지)
        $list.off("scroll.searchlist").on("scroll.searchlist", function () {
            if (search_lock) return;

            var el = this;
            var $el = $(this);
            var atBottom = (el.scrollTop + $el.innerHeight()) >= (el.scrollHeight - 2);

            if (!atBottom || search_offset >= results.length) return;

            search_lock = true;
            requestAnimationFrame(function () {
                renderSearchListPage(results, search_offset);
                search_lock = false;
            });
        });
    }

    // 페이지 단위 추가 렌더
    function renderSearchListPage(results, offset) {
        var $list = $("#search_result_list");
        var end = Math.min(offset + search_pageinsize, results.length);
        if (offset >= end) return;

        var currentNum = $("#display_number").text()||'';
        var nodes = [];

        for (var i = offset; i < end; i++) {
            var contact = results[i];
            var phone = pickPhone(contact, currentNum) || {};
            var $li = createSearchListItem();

            $li.find("a")
                .attr("data-user-id", contact.userId ?? "")
                .attr("data-phone", phone.normalized ?? "");

            if (contact.thumbUrl) {
                $li.find(".thumb").css("background-image", "url('" + contact.thumbUrl + "')");
            } else {
                $li.find(".thumb").removeAttr("style");
            }

            $li.find(".name").text(contact.name ?? "");
            $li.find(".num").text(phone.display ?? "");

            nodes.push($li[0]);
        }

        if (nodes.length) {
            $list.append(nodes);
            search_offset = end; // 다음 페이지 시작점 업데이트
        }
    }

    function openSearchList() { $(".search_list").removeClass('none'); }
    function closeSearchList() { $(".search_list").addClass('none'); }

    // 한 자리 추가
    function addDigit(digit) {
        if ($("#display_number").text().length >= MAX_NUMBER_LENGTH) {
            popAlert?.("16자리까지 입력 가능합니다.");
            return;
        }
        $("#display_number").text($("#display_number").text() + digit) ;
        try {
            if (typeof searchPad === "function") searchPad();
            if (Array.isArray(window.searchContactByNumber)) {
                renderPreview(window.searchContactByNumber, $("#display_number").text().replace(/\D/g, ""));
            }
        } catch (e) { }
    }

    // 한 자리 삭제
    function deleteDigit() {
        if ($("#display_number").text().length === 0) return;

        $("#display_number").text($("#display_number").text().slice(0,-1));

        if ($("#display_number").text().length == 0) {
            clearNumber();
            return;
        }

        try {
            if (typeof searchPad === "function") searchPad();
            if (Array.isArray(window.searchContactByNumber)) {
                renderPreview(window.searchContactByNumber, $("#display_number").text().replace(/\D/g, ""));
            }
        } catch (e) { }
    }

    // 전체 초기화
    function clearNumber() {
        $("#display_number").text('');
        $("#apx_preview").find(".apx_unit").remove();
        $("#apx_more_button").attr("data-total", "0").text("0");
        closeSearchList();
        try { if (typeof searchPad === "function") searchPad(); } catch (e) { }
    }

    // 클릭투콜 버튼
    function handleClickToCall() {
        const num = gformatter.number($("#display_number").text());
        if (!num) {
            if (!call_history_list || !call_history_list.length || !call_history_list[0].number) {
                console.log("전화번호를 입력해주세요.");
                if (typeof popAlert === "function") popAlert("전화 번호를 확인해 주세요");
                return;
            }
            $("#display_number").text(call_history_list[0].number);
            return;
        }
        clearNumber();
        clickToCall(num, "기타");
    }

    // 콜쓰루 버튼
    function handleCallThrough() {
        let num = $.trim($("#display_number").text() || "");

        $("#search_list_layer").addClass('none');

        if (!num) {
            if (!call_history_list || !call_history_list.length || !call_history_list[0].number) {
                console.log("전화번호를 입력해주세요.");
                if (typeof popAlert === "function") popAlert("전화 번호를 확인해 주세요");
                return;
            }
            $("#display_number").text(call_history_list[0].number);
            return;
        }
        clearNumber();
        callthrough(num, "기타");
    }

    // 콜백 버튼
    function handleCallBack() {
        let num = $.trim($("#display_number").text() || "");

        $("#search_list_layer").addClass('none');

        if (!num) {
            if (!call_history_list || !call_history_list.length || !call_history_list[0].number) {
                console.log("전화번호를 입력해주세요.");
                if (typeof popAlert === "function") popAlert("전화 번호를 확인해 주세요");
                return;
            }
            $("#display_number").text(call_history_list[0].number);
            return;
        }
        clearNumber();
        callBack(num, "기타");
    }

    // 키패드
    function getDigitText($a) {
        return $a.clone().children("sub").remove().end().text().trim();
    }

    // 번호로 연락처 검색
    function searchPad() {
        const rawText = $("#display_number").text()||'';
        const query = String(rawText).replace(/\D/g, ""); // 숫자만

        const $preview = $("#apx_preview");
        const $more = $("#apx_more_button");

        if (!query) {
            window.searchContactByNumber = [];
            $preview.addClass("is-empty").find(".apx_unit").remove();
            $more.attr("data-total", "0").text("0").hide();
            if (typeof closeSearchList === "function") closeSearchList();
            return [];
        }

        const contacts = Array.isArray(window.newContact)
            ? window.newContact
            : (typeof window.localStorage?.getArray === "function"
                ? (window.localStorage.getArray("contact") || [])
                : []);

        function toNormalizedContact(contact) {
            const phoneList = Array.isArray(contact?.phoneNumbers) ? contact.phoneNumbers : [];
            const normalizedPhones = phoneList.map((phoneEntry) => {
                const normalizedNumber = String(phoneEntry?.normalizedNumber || phoneEntry || "").replace(/\D/g, "");
                const displayNumber = phoneEntry?.display ||
                    (typeof formatPhoneDisplay === "function" ? formatPhoneDisplay(normalizedNumber) : normalizedNumber);
                return { normalizedNumber, display: displayNumber };
            });

            const thumbUrl =
                (typeof window.getThumbImage === "function" && contact?.thumbnail)
                    ? window.getThumbImage(contact.thumbnail)
                    : (contact?.thumbUrl || "");

            return {
                userId: contact?.userId || contact?.id || "",
                name: contact?.displayName || contact?.name || "",
                thumbUrl,
                phoneNumbers: normalizedPhones
            };
        }

        const matched = [];
        for (const c of contacts) {
            if (!c) continue;
            const nc = toNormalizedContact(c);
            const has = nc.phoneNumbers.some(ph => String(ph.normalizedNumber || "").includes(query));
            if (has) matched.push(nc);
        }

        window.searchContactByNumber = matched;

        if (matched.length === 0) {
            $preview.addClass("is-empty").find(".apx_unit").remove();
            $more.attr("data-total", "0").text("0").hide();
        } else {
            $preview.removeClass("is-empty");
            $more
                .attr("data-total", String(matched.length))
                .text(String(matched.length))
                .toggle(matched.length >= 2); // 핵심: 1개 이하면 숨김
        }

        return matched;
    }
    
    let init =  () => {

        if($.isEmptyObject(userData.dn)){
            $('#click_to_call').closest('li').removeClass('none');
        }else{
            switch (serverData.cust_func_code) {
                case '1':
                    $('#call_back').closest('li').removeClass('none');
                    break;
                case '2':
                case '3':
                    $('#call_through').closest('li').removeClass('none');
                    break;
                case '4':
                case '5':
                case '8':
                    $('#call_through, #click_to_call').closest('li').removeClass('none');
                    break;
                case '6':
                    $('#call_back, #call_through').closest('li').removeClass('none');
                    break;
                case '7':
                    $('#call_back, #call_through, #click_to_call').closest('li').removeClass('none');
                    break;
                case '9':
                    $('#call_back, #click_to_call').closest('li').removeClass('none');
                    break;
                default:
                    break;
            }
        }

        $("#display_number").text('');
        // 키패드
        $(".dials").off(".dial").on(`${INPUT_EVENT}.dial`, ".digits", function (e) {
            e.preventDefault();
            e.stopPropagation();

            const now = Date.now();
            if (now - lastInputTime < 100) return;
            lastInputTime = now;

            $(e.currentTarget).find('a').addClass('active');
            const text = getDigitText($(this).find('>a'));
            if (text === "Clear") {
                clearNumber();
            } else if (text === "Delete") {
                deleteDigit();
            } else if (text) {
                addDigit(text);
            }
        });
        $(".dials").on('touchend.dial', '.digits', (e)=>{
            $(e.currentTarget).find('a').removeClass('active');
        });
        $(".dials").on('touchcancel.dial', '.digits', (e)=>{
            $(e.currentTarget).find('a').removeClass('active');
        });

        $(".dials").on('touchstart', '.digits.delete a', (e)=>{
            pressTimer = setTimeout(()=>{
                clearNumber();
            }, 500);
        });
        $(".dials").on('touchend', '.digits.delete a', ()=>{
            clearTimeout(pressTimer);
        });




        $(document).off('keyup.dial').on('keyup.dial',function (e) {
            switch (e.which) {
                case 96: case 48: G.dial.addDigit("0"); break;
                case 97: case 49: G.dial.addDigit("1"); break;
                case 98: case 50: G.dial.addDigit("2"); break;
                case 99: case 51: G.dial.addDigit("3"); break;
                case 100: case 52: G.dial.addDigit("4"); break;
                case 101: case 53: G.dial.addDigit("5"); break;
                case 102: case 54: G.dial.addDigit("6"); break;
                case 103: case 55: G.dial.addDigit("7"); break;
                case 104: case 56: G.dial.addDigit("8"); break;
                case 105: case 57: G.dial.addDigit("9"); break;
                case 106: G.dial.addDigit("*"); break;
                case 107: G.dial.addDigit("#"); break;
                case 8: G.dial.deleteDigit(); break;
                case 27: G.dial.clearNumber(); break;
                case 13: $(".pad-action").click(); break;
                default: return;
            }
            e.preventDefault();
        });

        // 통화 버튼
        $("#click_to_call").off("click.dial").on("click.dial", function (e) {
            e.preventDefault();
            handleClickToCall();
        });
        $("#call_through").off("click.dial").on("click.dial", function (e) {
            e.preventDefault();
            handleCallThrough();
        });
        $("#call_back").off("click.dial").on("click.dial", function (e) {
            e.preventDefault();
            handleCallBack();
        });

        // 미리보기 선택
        $(document).off(".dial_apx").on("click.dial_apx", ".apx_unit", function (e) {
            e.preventDefault();
            const num = $(this).attr("data-phone") || "";
            if (!num) return;
            $("#display_number").text(num);
            try {
                if (typeof searchPad === "function") searchPad();
                if (Array.isArray(window.searchContactByNumber)) {
                    renderPreview(window.searchContactByNumber, $("#display_number").text().replace(/\D/g, ""));
                }
            } catch (e) { }
        });

        // 더보기 버튼
        $("#apx_more_button").off(".dial_more").on("click.dial_more", function (e) {
            e.preventDefault();
            if (!Array.isArray(window.searchContactByNumber) || window.searchContactByNumber.length === 0) return;

            renderSearchList(window.searchContactByNumber);
            openSearchList();
        });

        // 팝업 닫기
        $("#search_list_close").off(".dial_close").on("click.dial_close", function (e) {
            e.preventDefault();
            closeSearchList();
        });

        // 팝업 선택
        $("#search_result_list").off(".dial_pick").on("click.dial_pick", "li", function (e) {
            e.preventDefault();
            const num = $(this).find('>a').attr("data-phone") || "";
            if (!num) return;
            $("#display_number").text(num);
            closeSearchList();
            try {
                if (typeof searchPad === "function") searchPad();
                if (Array.isArray(window.searchContactByNumber)) {
                    renderPreview(window.searchContactByNumber, $("#display_number").text().replace(/\D/g, ""));
                }
            } catch (e) { }
        });

        let schemeData = localStorage.getItem('schemeData');
        if(!$.isEmptyObject(schemeData)){
            $("#display_number").text(schemeData);
            localStorage.removeItem('schemeData');
        }
    };

    G.init.dial = init;

})();