package saccubus.util;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 過去ログ取得時に指定する文字列(日付)をパースするユーティリティクラスです.
 * @author yuki
 */
public final class WayBackTimeParser {

    private static final Pattern PATTERN_NUMBER = Pattern.compile("^\\d+$");
    private static final Pattern PATTERN_YYMMDD_HH_MM_SS = Pattern.compile(
            "^(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)$");
    private static final Pattern PATTERN_YYMMDD_HH_MM = Pattern.compile(
            "^(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)$");
    private static final Pattern PATTERN_YYMMDD = Pattern.compile(
            "^(\\d+)\\D+(\\d+)\\D+(\\d+)$");

    private WayBackTimeParser() {
    }

    /**
     * 過去の時点を指定する文字列から、コメント取得フォーマットの"when"に指定する文字列へ変換します.
     * この文字列は、1970 年 1 月 1 日 00:00:00 GMT からの秒数(一般的なミリ秒ではない)になります.
     * @param time 時点指定文字列。"YYYY/MM/DD hh:mm:ss", "YYYY/MM/DD hh:mm", 秒数を表す数値,
     * ただし年月日時分(秒)の区切りは実際には数字以外のどんな文字でも構いません.
     * のいずれかであればパース可能です.
     * @return パース結果.
     * @throws IOException パース失敗.
     */
    public static long parse(String time) throws IOException {
        final Matcher mNumber = PATTERN_NUMBER.matcher(time);
        if (mNumber.matches()) {
            return Long.parseLong(time);
        }

        final Matcher mHMS = PATTERN_YYMMDD_HH_MM_SS.matcher(time);
        if (mHMS.matches()) {
            try {
                final DateFormat fmt = new SimpleDateFormat("yyyy:MM:dd:HH:mm:ss:");
                StringBuilder str = new StringBuilder();
                for (int i = 1; i <= 6; i++) {
                    str.append(mHMS.group(i));
                    str.append(":");
                }
                final Date date = fmt.parse(str.toString());
                return date.getTime() / 1000;
            } catch (ParseException ex) {
                throw new IOException("Cannot parse wayback time: " + time, ex);
            }
        }

        final Matcher mHM = PATTERN_YYMMDD_HH_MM.matcher(time);
        if (mHM.matches()) {
            try {
                final DateFormat fmt = new SimpleDateFormat("yyyy:MM:dd:HH:mm:");
                StringBuilder str = new StringBuilder();
                for (int i = 1; i <= 5; i++) {
                    str.append(mHM.group(i));
                    str.append(":");
                }
                final Date date = fmt.parse(str.toString());
                return date.getTime() / 1000;
            } catch (ParseException ex) {
                throw new IOException("Cannot parse wayback time: " + time, ex);
            }
        }

        final Matcher mYMD = PATTERN_YYMMDD.matcher(time);
        if (mYMD.matches()) {
            try {
                final DateFormat fmt = new SimpleDateFormat("yyyy:MM:dd:");
                StringBuilder str = new StringBuilder();
                for (int i = 1; i <= 3; i++) {
                    str.append(mYMD.group(i));
                    str.append(":");
                }
                final Date date = fmt.parse(str.toString());
                return date.getTime() / 1000;
            } catch (ParseException ex) {
                throw new IOException("Cannot parse wayback time: " + time, ex);
            }
        }


        throw new IOException("Cannot parse wayback time: " + time);
    }
}
