package edu.mingxu.jiaowu;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.View;
import android.widget.RemoteViews;

import org.json.JSONArray;
import org.json.JSONObject;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

final class WidgetRenderer {
    private static final int[] ROWS = {
        R.id.widget_row_one,
        R.id.widget_row_two,
        R.id.widget_row_three
    };
    private static final int[] TIMES = {
        R.id.widget_time_one,
        R.id.widget_time_two,
        R.id.widget_time_three
    };
    private static final int[] TITLES = {
        R.id.widget_item_title_one,
        R.id.widget_item_title_two,
        R.id.widget_item_title_three
    };
    private static final int[] SUBTITLES = {
        R.id.widget_item_subtitle_one,
        R.id.widget_item_subtitle_two,
        R.id.widget_item_subtitle_three
    };

    private WidgetRenderer() {}

    static void updateAll(Context context) {
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        int[] scheduleIds = manager.getAppWidgetIds(
            new ComponentName(context, ScheduleWidgetProvider.class));
        int[] examIds = manager.getAppWidgetIds(
            new ComponentName(context, ExamWidgetProvider.class));
        updateSchedule(context, manager, scheduleIds);
        updateExams(context, manager, examIds);
    }

    static void updateSchedule(
        Context context,
        AppWidgetManager manager,
        int[] appWidgetIds
    ) {
        JSONObject payload = payload(context);
        JSONArray items = payload.optJSONArray("schedule");
        boolean current = LocalDate.now().toString()
            .equals(payload.optString("scheduleDate"));
        render(
            context,
            manager,
            appWidgetIds,
            payload,
            current ? items : new JSONArray(),
            "今日课表",
            current ? "今天没有课程" : "打开 App 刷新今日课表",
            "timetable",
            1101);
    }

    static void updateExams(
        Context context,
        AppWidgetManager manager,
        int[] appWidgetIds
    ) {
        JSONObject payload = payload(context);
        render(
            context,
            manager,
            appWidgetIds,
            payload,
            payload.optJSONArray("exams"),
            "近期考试",
            "近期没有已发布考试",
            "exams",
            1201);
    }

    private static void render(
        Context context,
        AppWidgetManager manager,
        int[] appWidgetIds,
        JSONObject payload,
        JSONArray items,
        String title,
        String emptyText,
        String route,
        int requestCode
    ) {
        if (appWidgetIds == null || appWidgetIds.length == 0) {
            return;
        }

        for (int appWidgetId : appWidgetIds) {
            RemoteViews views = new RemoteViews(
                context.getPackageName(),
                R.layout.widget_academic);
            String displayName = payload.optString("displayName", "");
            views.setTextViewText(
                R.id.widget_title,
                displayName.trim().isEmpty() ? title : displayName + " · " + title);
            views.setTextViewText(
                R.id.widget_updated,
                updatedLabel(payload.optString("updatedAt")));

            int count = items == null ? 0 : Math.min(items.length(), ROWS.length);
            views.setViewVisibility(
                R.id.widget_empty,
                count == 0 ? View.VISIBLE : View.GONE);
            views.setTextViewText(
                R.id.widget_empty,
                payload.length() == 0 ? "登录 App 后同步教务数据" : emptyText);

            for (int index = 0; index < ROWS.length; index++) {
                if (index < count) {
                    JSONObject item = items.optJSONObject(index);
                    views.setViewVisibility(ROWS[index], View.VISIBLE);
                    views.setTextViewText(
                        TIMES[index],
                        item == null ? "" : item.optString("time"));
                    views.setTextViewText(
                        TITLES[index],
                        item == null ? "" : item.optString("title"));
                    views.setTextViewText(
                        SUBTITLES[index],
                        item == null ? "" : item.optString("subtitle"));
                } else {
                    views.setViewVisibility(ROWS[index], View.GONE);
                }
            }

            views.setOnClickPendingIntent(
                R.id.widget_root,
                openIntent(context, route, requestCode + appWidgetId));
            manager.updateAppWidget(appWidgetId, views);
        }
    }

    private static PendingIntent openIntent(
        Context context,
        String route,
        int requestCode
    ) {
        Intent intent = new Intent(
            Intent.ACTION_VIEW,
            Uri.parse("mingxu://open/" + route),
            context,
            MainActivity.class);
        intent.addFlags(
            Intent.FLAG_ACTIVITY_NEW_TASK |
            Intent.FLAG_ACTIVITY_CLEAR_TOP |
            Intent.FLAG_ACTIVITY_SINGLE_TOP);
        return PendingIntent.getActivity(
            context,
            requestCode,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
    }

    private static JSONObject payload(Context context) {
        String value = NativeHomePlugin.preferences(context)
            .getString(NativeHomePlugin.WIDGET_PAYLOAD, null);
        if (value == null || value.trim().isEmpty()) {
            return new JSONObject();
        }
        try {
            return new JSONObject(value);
        } catch (Exception ignored) {
            return new JSONObject();
        }
    }

    private static String updatedLabel(String value) {
        if (value == null || value.trim().isEmpty()) {
            return "等待同步";
        }
        try {
            Instant instant = Instant.parse(value);
            return "更新于 " + DateTimeFormatter.ofPattern("HH:mm")
                .withZone(ZoneId.systemDefault())
                .format(instant);
        } catch (Exception ignored) {
            return "最近已同步";
        }
    }
}
