%**************************************************************************
%   Name: CODIS_Rainfall_PlotterYY_v20260811a.m
%   Copyright:  
%   Author: HsiupoYeh 
%   Version: v20260811a
%   Description: 從中央氣象署 CODIS 系統抓取指定氣象站的日雨量與平均氣溫資料，
%       並使用 plotyy 繪製雙軸圖表，標註特定日期與數值，最後輸出PNG 圖檔。
%   呼叫方式:
%       直接執行此腳本即可。可在腳本開頭調整 target_date_str 與 Weather.StationID。
%       預設輸出檔名範例: 竹子湖_466930_雨量氣溫_20260101-20260701_標註20260601_1200x200.png
%**************************************************************************
clear; clc; close all;
% =========================================================================
% 0. 設定要特別標註的目標日期字串
%=========================================================================
target_date_str = '2026-06-01';
 
% =========================================================================
% 1. 查詢參數設定
% =========================================================================
Weather.StationID   = '466930';     % 氣象站代號 (466930 代表竹子湖)
Weather.StationName = '竹子湖';       % 氣象站中文名稱      
start_date = '2026-01-01T00:00:00';    % 資料查詢起始時間 (ISO 8601 格式)
end_date   = '2026-07-01T00:00:00';    % 資料查詢結束時間 (ISO 8601 格式)
  
    % =========================================================================
    % 2. URL Encode (使用 R2014a 相容的 Java API 進行網址編碼)
    % =========================================================================
    enc_start = char(java.net.URLEncoder.encode(start_date, 'UTF-8'));
    enc_end   = char(java.net.URLEncoder.encode(end_date, 'UTF-8'));

    % 組合 POST 請求的 payload 資料
    postData = sprintf('date=%s&type=report_month&stn_ID=%s&stn_type=cwb&more=&start=%s&end=%s&item=', ...
        enc_start, Weather.StationID, enc_start, enc_end);

    % =========================================================================
    % 3. 執行 curl.exe 抓取 API 資料
    % =========================================================================
    url = 'https://codis.cwa.gov.tw/api/station';
    curlCmd = sprintf([ ...
        'curl.exe -s "%s" ' ...
        '-H "Accept: application/json, text/javascript, */*; q=0.01" ' ...
        '-H "Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7" ' ...
        '-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" ' ...
        '-H "Origin: https://codis.cwa.gov.tw" ' ...
        '-H "Referer: https://codis.cwa.gov.tw/StationData" ' ...
        '-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" ' ...
        '-H "X-Requested-With: XMLHttpRequest" ' ...
        '--data-raw "%s"' ...
    ], url, postData);

    % 執行命令列 curl 指令
    [status, jsonText] = system(curlCmd);

    % 檢查執行狀態與回傳內容是否有效
    if status ~= 0 || isempty(jsonText)
        error('curl 執行失敗，請確認網路連線是否正常。');
    end

    % 將 JSON 文字解析為 MATLAB 結構體 (需確保路徑中含有 json_decode 函式)
    jsonData = json_decode(jsonText);

    % =========================================================================
    % 4. 資料提取與解析
    % =========================================================================
    % 提取日期時間字串並轉為 MATLAB 日期序列值 (datenum)
    Weather.DataDate = {jsonData.data.dts.DataDate}';
    Weather.DataNumber = datenum(Weather.DataDate, 'yyyy-mm-ddTHH:MM:SS');

    % 提取平均氣溫資料
    temp_AirTemperature    = [jsonData.data.dts.AirTemperature]';
    Weather.AirTemperature = [temp_AirTemperature.Mean]';

    % 提取累積雨量資料，並將小於 0.5 mm 的微量降雨視為 0
    temp_Precipitation    = [jsonData.data.dts.Precipitation]';
    Weather.Precipitation = [temp_Precipitation.Accumulation]';
    Weather.Precipitation(Weather.Precipitation < 0.5) = 0;

    % =========================================================================
    % 5. 使用 plotyy 建立雙軸圖表
    % =========================================================================
    % 建立視窗，指定背景為白色，並調整長寬比例 (1200x200 適合寬螢幕橫幅顯示)
    fig = figure('Color', 'w', 'Position', [10, 100, 1200, 200]);

    % 繪製雙軸圖：左軸為長條圖 (雨量)、右軸為折線圖 (氣溫)
    [ax, bar_Precipitation_handle, plot_AirTemperature_handle] = plotyy(Weather.DataNumber, Weather.Precipitation, ...
                          Weather.DataNumber, Weather.AirTemperature, ...
                          @bar, @plot);

    % 5.1 設定左軸（雨量長條圖）樣式與範圍
    set(bar_Precipitation_handle, 'FaceColor', [0.3 0.6 0.8], 'EdgeColor', 'none'); % 填滿淺藍色
    set(bar_Precipitation_handle, 'EdgeColor', 'k', 'LineWidth', 0.5);              % 設定長條圖黑色外框與線寬
    set(ax(1), 'YColor', [0.3 0.6 0.8]);                                           % 左軸座標軸顏色
    ylabel(ax(1), '雨量 (mm)');                                                      % 左軸標籤
    ylim(ax(1), [0 500]);                                                           % 設定雨量範圍 (0 ~ 500 mm)
    set(ax(1), 'YTick', 0:100:500);                                                 % 設定雨量刻度間距 (每 100mm 一格)

    % 5.2 設定右軸（氣溫折線圖）樣式與範圍
    set(plot_AirTemperature_handle, 'Color', [0.85 0.2 0.2], 'LineWidth', 1.2);    % 設定折線顏色為深紅色與線寬
    set(ax(2), 'YColor', [0.85 0.2 0.2]);                                           % 右軸座標軸顏色
    ylabel(ax(2), '氣溫 (°C)');                                                      % 右軸標籤
    ylim(ax(2), [0 40]);                                                           % 設定氣溫範圍 (0 ~ 40 °C)
    set(ax(2), 'YTick', 0:10:40);                                                   % 設定氣溫刻度間距 (每 10 °C 一格)

    % 5.3 找出每月 1 號與指定目標日期的索引位置
    dv = datevec(Weather.DataNumber);
    idx_first_day = find(dv(:, 3) == 1);                                            % 取得每月第一天的索引
    target_datenum = datenum(target_date_str, 'yyyy-mm-dd');
    idx_target = find(floor(Weather.DataNumber) == target_datenum);                 % 取得目標日期的索引

    title_extra = '';

    % 5.4 若找到指定目標日期，於左軸繪製垂直虛線並將數值串接至圖表標題
    if ~isempty(idx_target)
        x_val = Weather.DataNumber(idx_target);
        y_rain = Weather.Precipitation(idx_target);
        y_temp = Weather.AirTemperature(idx_target);

        hold(ax(1), 'on');
        plot(ax(1), [x_val, x_val], [0, 500], 'k--', 'LineWidth', 1);               % 繪製點狀垂直標註線    
        title_extra = sprintf(' [%s 雨量: %.1f mm | 氣溫: %.1f °C]', ...
            datestr(x_val, 'yyyy-mm-dd'), y_rain, y_temp);
    end

    % 5.5 同步設定兩側 X 軸範圍與刻度（對齊左右軸的時間軸）
    x_lim = [min(Weather.DataNumber)-0.5, max(Weather.DataNumber)+0.5];
    for i = 1:2
        set(ax(i), 'XTick', Weather.DataNumber(idx_first_day));                    % X 軸刻度設在每月初
        datetick(ax(i), 'x', 'yyyy-mm-dd', 'keepticks', 'keeplimits');             % 格式化日期顯示
        xlim(ax(i), x_lim);                                                        % 固定 X 軸邊界
    end

    box off
    % 5.6 在圖表頂部補上一條黑色封閉邊框線
    hold(ax(1), 'on');
    plot(ax(1), x_lim, [500, 500], 'k', 'LineWidth', 1.2);

    % 5.7 版面與標題微調
    title(ax(1), [Weather.StationName ' (' Weather.StationID ') 日累積雨量與平均氣溫' title_extra]);
    xlabel(ax(1), '日期'); 

    % 移除多餘邊距
    set(ax(1), 'LooseInset', get(ax(1), 'TightInset'));
    set(ax(2), 'LooseInset', get(ax(2), 'TightInset'));

    % 調整圖表在視窗中的定位與大小比例 [left, bottom, width, height]
    set(ax(1), 'Position', [0.06, 0.22, 0.88, 0.63]);
    set(ax(2), 'Position', [0.06, 0.22, 0.88, 0.63]);

    % =========================================================================
    % 6. 圖檔輸出與存檔設定
    % =========================================================================
    str_start  = datestr(min(Weather.DataNumber), 'yyyymmdd');
    str_end    = datestr(max(Weather.DataNumber), 'yyyymmdd');
    str_target = datestr(target_datenum, 'yyyymmdd');

    % 動態產生具備站名、日期區間與標註日期的 PNG 檔名
    pngFilename = sprintf('%s_%s_雨量氣溫_%s-%s_標註%s_1200x200.png', ...
        Weather.StationName, Weather.StationID, str_start, str_end, str_target);

    % 設定列印紙張模式並以 300 DPI 高解析度輸出 PNG
    set(fig, 'PaperPositionMode', 'auto');
    print(fig, pngFilename, '-dpng', '-r300');
    fprintf('圖形已成功儲存為：%s\n', pngFilename);