/*
 * 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.
 *
 */
package org.apache.ant.props.stringops;

import java.text.ParsePosition;

import org.apache.ant.props.RegexBasedEvaluator;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.RegularExpression;
import org.apache.tools.ant.util.regexp.Regexp;

/**
 * Abstract pattern-based operation.
 */
public abstract class PatternOperation extends RegexBasedEvaluator {
    private interface PatternParser {
        boolean process(StringBuffer sb, ParsePosition pos);
    }

    private static class RecognizeCrossPlatformSeparators implements PatternParser {
        public boolean process(StringBuffer sb, ParsePosition pos) {
            int index = pos.getIndex();
            int matchLength = sb.indexOf("\\\\", index) == index ? 2
                    : sb.charAt(index) == '/' ? 1 : 0;
            if (matchLength > 0) {
                sb.replace(index, index + matchLength, "[/|\\\\]");
                pos.setIndex(index + 6);
                return true;
            }
            return false;
        }
    }

    private static class PreserveEscapes implements PatternParser {
        public boolean process(StringBuffer sb, ParsePosition pos) {
            int index = pos.getIndex();
            if (sb.charAt(index) == '\\') {
                pos.setIndex(index + 2);
                return true;
            }
            return false;
        }
    }

    private static class CharToPattern implements PatternParser {
        private char patternChar;
        private String regexpPattern;
        CharToPattern(char patternChar, String regexpPattern) {
            this.patternChar = patternChar;
            this.regexpPattern = regexpPattern;
        }
        public boolean process(StringBuffer sb, ParsePosition pos) {
            int index = pos.getIndex();
            if (sb.charAt(index) == patternChar) {
                sb.replace(index, index + 1, regexpPattern);
                pos.setIndex(index + regexpPattern.length());
                return true;
            }
            return false;
        }
    }

    //order is important:
    private static final PatternParser[] GREEDY_PARSERS = new PatternParser[] {
        new RecognizeCrossPlatformSeparators(),
        new PreserveEscapes(),
        new CharToPattern('?', "."),
        new CharToPattern('.', "\\."),
        new CharToPattern('*', ".*")
    };

    private static final PatternParser[] RELUCTANT_PARSERS = new PatternParser[] {
        new RecognizeCrossPlatformSeparators(),
        new PreserveEscapes(),
        new CharToPattern('?', "."),
        new CharToPattern('.', "\\."),
        new CharToPattern('*', ".*?")
    };

    /**
     * Construct a new PatternOperation.
     */
    protected PatternOperation(String regex) {
        super(regex);
    }

    /**
     * Convert a *nix-style pattern to a regex pattern.
     * @param sb StringBuffer to convert.
     */
    protected void convertToRegex(StringBuffer sb) {
        convertToRegex(sb, true);
    }

    /**
     * Convert a *nix-style pattern to a regex pattern.
     * @param sb StringBuffer to convert.
     * @param greedy whether to be greedy.
     */
    protected void convertToRegex(StringBuffer sb, boolean greedy) {
        ParsePosition pos = new ParsePosition(0);
        PatternParser[] parsers = greedy ? GREEDY_PARSERS : RELUCTANT_PARSERS;
nextpos:
        while (pos.getIndex() < sb.length()) {
            for (int i = 0; i < parsers.length; i++) {
                if (parsers[i].process(sb, pos)) {
                    continue nextpos;
                }
            }
            pos.setIndex(pos.getIndex() + 1);
        }
    }

    /**
     * Convert a *nix-style pattern to a regex pattern.
     * @param pattern the *nix-style pattern.
     * @return String regex pattern.
     */
    protected String toRegex(String pattern) {
        return toRegex(pattern, true);
    }

    /**
     * Convert a *nix-style pattern to a regex pattern.
     * @param pattern the *nix-style pattern.
     * @param greedy whether to be greedy.
     * @return String regex pattern.
     */
    protected String toRegex(String pattern, boolean greedy) {
        if (pattern == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer(pattern);
        ParsePosition pos = new ParsePosition(0);
        PatternParser[] parsers = greedy ? GREEDY_PARSERS : RELUCTANT_PARSERS;
nextpos:
        while (pos.getIndex() < sb.length()) {
            for (int i = 0; i < parsers.length; i++) {
                if (parsers[i].process(sb, pos)) {
                    continue nextpos;
                }
            }
            pos.setIndex(pos.getIndex() + 1);
        }
        return sb.toString();
    }

    /**
     * Create an Ant Regexp object.
     * @param pattern the regex pattern to use.
     * @param project the associated Project instance.
     * @return Regexp
     */
    protected Regexp createRegexp(String pattern, Project project) {
        RegularExpression re = new RegularExpression();
        re.setPattern(pattern);
        return re.getRegexp(project);
    }

    /**
     * De-escape a given character.
     * @param c the character to "unmask".
     * @param sb the target StringBuffer.
     */
    protected void deEscape(char c, StringBuffer sb) {
        ParsePosition pos = new ParsePosition(0);
        for (int index = pos.getIndex(); index < sb.length(); index = pos.getIndex()) {
            if (sb.charAt(index) == '\\' && sb.charAt(index + 1) == c) {
                sb.deleteCharAt(index);
            }
            pos.setIndex(index + 1);
        }
    }
}
