        catActiveColumn += dir;
        if (catActiveColumn < 0) catActiveColumn = 0;
        if (catActiveColumn > 1) catActiveColumn = 1;

        reconstruirMenus();

        if (menuState == 2 && catMenu != null) catMenu.setVisibility(View.VISIBLE);
    }


    private ChannelItem canalEnFoco() {
        if (channelItems == null || channelItems.size() == 0) return null;
        if (focusedChannelIndex < 0) focusedChannelIndex = 0;
        if (focusedChannelIndex >= channelItems.size()) focusedChannelIndex = channelItems.size() - 1;
        return channelItems.get(focusedChannelIndex);
    }


    private void cargarEpgCanalEnfocado() {
        ChannelItem ch = canalEnFoco();
        if (ch == null || ch.sid == null || ch.sid.trim().isEmpty()) return;

        final String sid = ch.sid;

        if (focusedEpgLoading) return;
        if (sid.equals(lastFocusedEpgSid) && ch.programs != null && ch.programs.size() >= 10) return;

        focusedEpgLoading = true;
        lastFocusedEpgSid = sid;

        new Thread(() -> {
            try {
                String api = "http://216.152.155.250/PUNTOZ_PANEL/tv_clean.php?ajax_epg=1&stream_id=" + URLEncoder.encode(sid, "UTF-8");
                URL u = new URL(api);
                HttpURLConnection c = (HttpURLConnection) u.openConnection();
                c.setConnectTimeout(3500);
                c.setReadTimeout(6000);
                c.setRequestProperty("User-Agent", "Puntoz-TV-Android");
                InputStream is = c.getInputStream();

                byte[] buf = new byte[8192];
                StringBuilder sb = new StringBuilder();
                int n;
                while ((n = is.read(buf)) > 0) sb.append(new String(buf, 0, n, "UTF-8"));
                is.close();

                JSONObject json = new JSONObject(sb.toString());

                for (int i = 0; i < channelItems.size(); i++) {
                    ChannelItem x = channelItems.get(i);
                    if (x.sid.equals(sid)) {
                        x.now = json.optString("now", x.now);
                        x.next = json.optString("next", x.next);
                        x.st = String.valueOf(json.optLong("start", 0));
                        x.en = String.valueOf(json.optLong("end", 0));
                        x.ns = String.valueOf(json.optLong("next_start", 0));
                        x.ne = String.valueOf(json.optLong("next_end", 0));

                        JSONArray arrProg = json.optJSONArray("programs");
                        if (arrProg != null) {
                            ArrayList<EpgItem> tmpPrograms = new ArrayList<>();
                            for (int pz = 0; pz < arrProg.length(); pz++) {
                                JSONObject po = arrProg.getJSONObject(pz);
                                EpgItem ei = new EpgItem();
                                ei.title = po.optString("title", "Programación");
                                ei.desc = po.optString("desc", "");
                                ei.start = po.optLong("start", 0);
                                ei.stop = po.optLong("end", po.optLong("stop", 0));
                                if (ei.start > 0 && ei.stop > ei.start) tmpPrograms.add(ei);
                            }
                            x.programs = tmpPrograms;
                        }
                        break;
                    }
                }

                runOnUiThread(() -> {
                    lastFocusedEpgSid = "";
                    reconstruirMenus();
                    if (menuState == 1 && guideMenu != null) guideMenu.setVisibility(View.VISIBLE);
                    if (menuState == 2 && catMenu != null) catMenu.setVisibility(View.VISIBLE);
                    cargarEpgCanalEnfocado();
                });

            } catch(Exception ignored) {
            } finally {
                focusedEpgLoading = false;
            }
        }).start();
    }


    private void moverCanalFoco(int delta) {
        if (channelItems == null || channelItems.size() == 0) return;

        focusedChannelIndex += delta;
        if (focusedChannelIndex < 0) focusedChannelIndex = 0;
        if (focusedChannelIndex >= channelItems.size()) focusedChannelIndex = channelItems.size() - 1;

        reconstruirMenus();

        if (menuState == 1 && guideMenu != null) guideMenu.setVisibility(View.VISIBLE);
        if (menuState == 2 && catMenu != null) catMenu.setVisibility(View.VISIBLE);

        cargarEpgCanalEnfocado();
    }


    private static class EpgItem {
                    mostrarCategoriasMenu();
                } else if (menuState == 2) {
                    if (catActiveColumn == 1) {
                        moverColumnaCategoria(-1);
                    } else {
                        cerrarMenus();
                    }
                }
                return true;
            }

            if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
                if (menuState == 2) {
                    if (catActiveColumn == 0) {
                        moverColumnaCategoria(1);
                    } else {
                        mostrarGuiaMenu();
                    }
                    return true;
                }
            }

            if (key == KeyEvent.KEYCODE_DPAD_UP) {
                if (menuState == 1) {
                    moverCanalFoco(-1);
                    return true;
                }
                if (menuState == 2) {
                    if (catActiveColumn == 0) moverCategoriaFoco(-1);
                    else moverCanalFoco(-1);
                    return true;
                }
            }

            if (key == KeyEvent.KEYCODE_DPAD_DOWN) {
                if (menuState == 1) {
                    moverCanalFoco(1);
                    return true;
                }
                if (menuState == 2) {
                    if (catActiveColumn == 0) moverCategoriaFoco(1);
                    else moverCanalFoco(1);
                    return true;
                }
            }

            if (key == KeyEvent.KEYCODE_BACK) {
                if (menuState != 0) {
                    cerrarMenus();
                    return true;
                }
69:    int focusedChannelIndex = 0;
74:    int maxVisibleChannels = 18;
101:    boolean focusedEpgLoading = false;
102:    String lastFocusedEpgSid = "";
146:                focusedChannelIndex = i;
357:            int chStart = Math.max(0, focusedChannelIndex - (maxVisibleChannels / 2));
358:            if (chStart + maxVisibleChannels > channelItems.size()) chStart = Math.max(0, channelItems.size() - maxVisibleChannels);
360:            for (int i = chStart; i < channelItems.size() && i < chStart + maxVisibleChannels; i++) {
362:                boolean foco = i == focusedChannelIndex;
466:            int chCatStart = Math.max(0, focusedChannelIndex - (maxVisibleChannels / 2));
467:            if (chCatStart + maxVisibleChannels > channelItems.size()) chCatStart = Math.max(0, channelItems.size() - maxVisibleChannels);
469:            for (int i = chCatStart; i < channelItems.size() && i < chCatStart + maxVisibleChannels; i++) {
471:                boolean foco = (catActiveColumn == 1 && i == focusedChannelIndex);
523:                focusedChannelIndex = i;
539:        focusedChannelIndex = playingChannelIndex;
546:        lastFocusedEpgSid = "";
548:        cargarEpgCanalEnfocado();
557:        lastFocusedEpgSid = "";
559:        cargarEpgCanalEnfocado();
585:                focusedChannelIndex = i;
640:                focusedChannelIndex = i;
646:        if (!foundPlaying) focusedChannelIndex = 0;
653:        lastFocusedEpgSid = "";
724:                            focusedChannelIndex = k;
730:                    if (!foundPlaying && focusedChannelIndex >= channelItems.size()) {
731:                        focusedChannelIndex = 0;
739:                    lastFocusedEpgSid = "";
743:                    cargarEpgCanalEnfocado();
761:        focusedChannelIndex = 0;
762:        lastFocusedEpgSid = "";
952:        if (focusedChannelIndex < 0) focusedChannelIndex = 0;
953:        if (focusedChannelIndex >= channelItems.size()) focusedChannelIndex = channelItems.size() - 1;
954:        return channelItems.get(focusedChannelIndex);
958:    private void cargarEpgCanalEnfocado() {
964:        if (focusedEpgLoading) return;
965:        if (sid.equals(lastFocusedEpgSid) && ch.programs != null && ch.programs.size() >= 10) return;
967:        focusedEpgLoading = true;
968:        lastFocusedEpgSid = sid;
1017:                    lastFocusedEpgSid = "";
1021:                    cargarEpgCanalEnfocado();
1026:                focusedEpgLoading = false;
1032:    private void moverCanalFoco(int delta) {
1035:        focusedChannelIndex += delta;
1036:        if (focusedChannelIndex < 0) focusedChannelIndex = 0;
1037:        if (focusedChannelIndex >= channelItems.size()) focusedChannelIndex = channelItems.size() - 1;
1044:        cargarEpgCanalEnfocado();
1324:                    moverCanalFoco(-1);
1329:                    else moverCanalFoco(-1);
1336:                    moverCanalFoco(1);
1341:                    else moverCanalFoco(1);
