package de.duehl.basics.logic;

/*
 * Copyright 2016 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
 */

/**
 * Dieses Klasse testet Strings darauf, ob sich Beginn- und Endzeichen
 * überlappen. Anwenden lässt sie sich für '<' und '>' oder für '&' und ';'
 * oder sonstige Fälle, in denen sich solche Zeichen nicht überlappen dürfen.
 *
 * @version 1.01     2013-12-12
 * @author Christian Dühl
 */

public class BeginAndEndTester {

    /**
     * Diese innere Klasse stellt ein Resultat mit eventueller Fehlermeldung
     * dar.
     */
    public class Result {

        /** Ergebnis der Untersuchung. */
        private final boolean ok;

        /** Fehlermeldung bei negativem Ergebnis. */
        private final String errorMesssage;

        /**
         * Konstruktor.
         *
         * @param ok
         *            Ergebnis der Untersuchung.
         * @param errorMesssage
         *            Fehlermeldung bei negativem Ergebnis.
         */
        public Result(final boolean ok, final String errorMesssage) {
            this.ok = ok;
            this.errorMesssage = errorMesssage;
        }

        /** Getter für das Ergebnis der Untersuchung. */
        public boolean isOk() {
            return ok;
        }

        /** Getter für die Fehlermeldung bei negativem Ergebnis. */
        public String getErrorMesssage() {
            return errorMesssage;
        }

    }

    /** Anfangszeichen. */
    private final char begin;

    /** Endzeichen. */
    private final char end;

    /**
     * Konstruktor.
     *
     * @param begin
     *            Anfangszeichen.
     * @param end
     *            Endzeichen.
     */
    public BeginAndEndTester(final char begin, final char end) {
        this.begin = begin;
        this.end = end;
    }

    /**
     * Überprüft einen Text auf fehlerhafte Vorkommnisse des Anfangs- und
     * Endzeichens. Erwartete wird, dass immer ein Endzeichen auf ein
     * Anfangszeichen folgt.
     *
     * @param text
     *            Zu überprüfender Text.
     * @return Untersuchungsergebnis mit Beschreibung des Fehlers, wenn das
     *         Ergebnis negativ ist.
     */
    public Result check(final String text) {
        int index = 0;
        int lastBeginPosition = -1;
        boolean foundBegin = false;
        for (char c : text.toCharArray()) {
            if (c == begin) {
                if (foundBegin) {
                    return new Result(false, "Letztes '" + begin
                            + "' an Stelle " + lastBeginPosition
                            + " ist nicht mit '" + end + "' beendet worden!");
                }
                else {
                    foundBegin = true;
                    lastBeginPosition = index;
                }
            }
            else if (c == end) {
                if (foundBegin) {
                    foundBegin = false;
                    lastBeginPosition = -1;
                }
                else {
                    return new Result(false, "Ein '" + end
                            + "' wurde an  Stelle " + index
                            + " gefunden ohne vorheriges '" + begin + "'!");
                }
            }

            index++;
        }
        if (foundBegin) {
            return new Result(false, "Letztes '" + begin
                    + "' an Stelle " + lastBeginPosition
                    + " ist nicht mit '" + end + "' beendet worden!");
        }
        return new Result(true,  "");
    }

}
