/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.fop.layoutmgr;

/**
 * An instance of this class represents information about a feasible
 * breaking point; it does not represent any piece of content.
 *
 * A KnuthPenalty is a feasible breaking point unless its value is infinity;
 * a KnuthPenalty whose value is -infinity represents a forced break.
 *
 * A KnuthPenalty is suppressed, and its width is ignored, if it is not a
 * chosen breaking point; for example, a KnuthPenalty representing a
 * hyphenation point has a width (the "-" width), which must be ignored if
 * that point is not chosen as a breaking point.
 *
 * Besides the inherited methods and attributes, this class has two more
 * attributes and the methods used to get them: the penalty value, which is
 * a kind of "aesthetic cost" (the higher the value, the more unsightly the
 * breaking point), and a boolean that marks KnuthPenalties which should not
 * be chosen as breaking points for consecutive lines.
 */
public class KnuthPenalty extends KnuthElement {

    /** Used for flagged penalties. See Knuth algorithm. */
    public static final int FLAGGED_PENALTY = 50;
    /** Dummy, zero-width penalty */
    public static final KnuthPenalty DUMMY_ZERO_PENALTY
            = new KnuthPenalty(0, 0, false, null, true);

    private int penalty;
    private boolean penaltyFlagged;
    private int breakClass = -1;

    /**
     * Create a new KnuthPenalty.
     *
     * @param width the width of this penalty
     * @param penalty the penalty value of this penalty
     * @param penaltyFlagged is this penalty flagged?
     * @param pos the Position stored in this penalty
     * @param auxiliary is this penalty auxiliary?
     */
    public KnuthPenalty(int width, int penalty, boolean penaltyFlagged, Position pos,
                        boolean auxiliary) {
        super(width, pos, auxiliary);
        this.penalty = penalty;
        this.penaltyFlagged = penaltyFlagged;
    }

    /**
     * Create a new KnuthPenalty.
     *
     * @param width the width of this penalty
     * @param penalty the penalty value of this penalty
     * @param penaltyFlagged is this penalty flagged?
     * @param breakClass the break class of this penalty (one of
     *   {@link org.apache.fop.fo.Constants#EN_AUTO},
     *   {@link org.apache.fop.fo.Constants#EN_COLUMN},
     *   {@link org.apache.fop.fo.Constants#EN_PAGE},
     *   {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE},
     *   {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}).
     * @param pos the Position stored in this penalty
     * @param isAuxiliary is this penalty auxiliary?
     */
    public KnuthPenalty(int width, int penalty, boolean penaltyFlagged, int breakClass,
                        Position pos, boolean isAuxiliary) {
        this(width, penalty, penaltyFlagged, pos, isAuxiliary);
        this.breakClass = breakClass;
    }

    private static String getBreakClassName(int breakClass) {
        return AbstractBreaker.getBreakClassName(breakClass);
    }

    /**
     * Get the penalty's value as a {@link java.lang.String}.
     * (Mainly used in {@link #toString()} methods, to improve readability
     * of the trace logs.)
     *
     * TODO: shouldn't be penalty a class of its own?
     *
     * @param penaltyValue  the penalty value
     * @return  the penalty value as a {@link java.lang.String}
     */
    protected static String valueOf(int penaltyValue) {
        String result = (penaltyValue < 0) ? "-" : "";
        int tmpValue = Math.abs(penaltyValue);
        result += (tmpValue == KnuthElement.INFINITE)
                ? "INFINITE"
                : String.valueOf(tmpValue);
        return result;
    }

    /** {@inheritDoc} */
    public boolean isPenalty() {
        return true;
    }

    /**
     * @return the penalty value of this penalty.
     */
    public int getPenalty() {
        return penalty;
    }

    /**
     * Sets a new penalty value.
     * @param penalty the new penalty value
     */
    public void setPenalty(int penalty) {
        this.penalty = penalty;
    }

    /** @return true is this penalty is a flagged one. */
    public boolean isPenaltyFlagged() {
        return penaltyFlagged;
    }

    /** {@inheritDoc} */
    public boolean isForcedBreak() {
        return penalty == -KnuthElement.INFINITE;
    }

    /**
     * @return the break class of this penalty (EN_AUTO, EN_COLUMN, EN_PAGE, EN_EVEN_PAGE,
     * EN_ODD_PAGE)
     */
    public int getBreakClass() {
        return breakClass;
    }

    /** {@inheritDoc} */
    public String toString() {
        StringBuffer buffer = new StringBuffer(64);
        if (isAuxiliary()) {
            buffer.append("aux. ");
        }
        buffer.append("penalty");
        buffer.append(" p=");
        buffer.append(valueOf(this.penalty));
        if (this.penaltyFlagged) {
            buffer.append(" [flagged]");
        }
        buffer.append(" w=");
        buffer.append(getWidth());
        if (isForcedBreak()) {
            buffer.append(" (forced break, ")
                    .append(getBreakClassName(this.breakClass))
                    .append(")");
        } else if (this.penalty >= 0 && this.breakClass != -1) {
            //penalty corresponding to a keep constraint
            buffer.append(" (keep constraint, ")
                    .append(getBreakClassName(this.breakClass))
                    .append(")");
        }
        return buffer.toString();
    }
}
