package de.duehl.basics.datetime.date.parse;

/*
 * Copyright 2018 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.util.HashMap;
import java.util.Map;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.text.Text;

/**
 * Diese Klasse stellt die abstrakte Basis einer Methode zum Parsen eines Datums aus einem String
 * dar.
 *
 * @version 1.01     2018-11-16
 * @author Christian Dühl
 */

abstract class DateParseMethod {

    private static final Map<String, Integer> MONTH_NAME_TO_NUMBER_MAP = createMonthNameToNumberMap();

    private final String dateToParse;
    private final Pattern pattern;
    protected Matcher matcher;
    private ImmutualDate parsedDate;
    private boolean success;

    public DateParseMethod(String dateToParse, Pattern pattern) {
        this.dateToParse = dateToParse;
        this.pattern = pattern;
    }

    public void parse() {
        matcher = pattern.matcher(dateToParse);
        success = matcher.matches();
        if (success) {
            parsedDate = createDateFromMatcher();
        }
    }

    protected abstract ImmutualDate createDateFromMatcher();

    public boolean isSuccessfull() {
        return success;
    }

    public ImmutualDate getParsedDate() {
        return parsedDate;
    }

    private static Map<String, Integer> createMonthNameToNumberMap() {
        Map<String, Integer> map = new HashMap<>();

        map.put("Januar", 1);
        map.put("Jan", 1);
        map.put("January", 1);

        map.put("Februar", 2);
        map.put("Feb", 2);
        map.put("February", 2);

        map.put("März", 3);
        map.put("Maerz", 3);
        map.put("Mär", 3);
        map.put("March", 3);
        map.put("Mar", 3);

        map.put("April", 4);
        map.put("Apr", 4);

        map.put("Mai", 5);
        map.put("May", 5);

        map.put("Juni", 6);
        map.put("Jun", 6);
        map.put("June", 6);

        map.put("Juli", 7);
        map.put("Jul", 7);
        map.put("July", 7);

        map.put("August", 8);
        map.put("Aug", 8);

        map.put("September", 9);
        map.put("Sep", 9);
        map.put("Sept", 9);

        map.put("Oktober", 10);
        map.put("Okt", 10);
        map.put("October", 10);
        map.put("Oct", 10);

        map.put("November", 11);
        map.put("Nov", 11);

        map.put("Dezember", 12);
        map.put("Dez", 12);
        map.put("December", 12);
        map.put("Dec", 12);

        return map;
    }

    /**
     * Versucht aus einem Monat als String einen numerischen Monat zwischen 1
     * und 12 zu erzeugen.
     *
     * @param month
     *            Monat als String wie "Feb." oder "Juni".
     * @return Zahl zwischen 1 und 12 für die Monate Januar bis Dezember oder 0,
     *         wenn der Monat nicht erkannt wurde.
     */
    protected static int translateMonthFromStringToInt(String month) {
        String editedMonth = Text.removeTextAtEndIfEndsWith(month, ".");

        for (String key : MONTH_NAME_TO_NUMBER_MAP.keySet()) {
            if (editedMonth.equals(key)) {
                return MONTH_NAME_TO_NUMBER_MAP.get(key);
            }
        }

        return 0;
    }

}
