/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.repackage;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Repackager {

    private final List<List<String>> _fromPackages = new ArrayList<>();
    private final List<List<String>> _toPackages = new ArrayList<>();

    private Matcher[] _fromMatchers;
    private String[] _toPackageNames;

    public Repackager(String repackageSpecs) {
        List<String> repackages = splitPath(repackageSpecs, ';');

        // Sort the repackage spec so that longer from's are first to match
        // longest package first

        for (; ; ) {
            boolean swapped = false;

            for (int i = 1; i < repackages.size(); i++) {
                String spec1 = repackages.get(i - 1);
                String spec2 = repackages.get(i);

                if (spec1.indexOf(':') < spec2.indexOf(':')) {
                    repackages.set(i - 1, spec2);
                    repackages.set(i, spec1);

                    swapped = true;
                }
            }

            if (!swapped) {
                break;
            }
        }

        for (String repackage : repackages) {

            int j = repackage.indexOf(':');

            if (j < 0 || repackage.indexOf(':', j + 1) >= 0) {
                throw new RuntimeException("Illegal repackage specification: " + repackage);
            }

            String from = repackage.substring(0, j);
            String to = repackage.substring(j + 1);

            _fromPackages.add(Repackager.splitPath(from, '.'));
            _toPackages.add(Repackager.splitPath(to, '.'));
        }

        _fromMatchers = new Matcher[_fromPackages.size() * 2];
        _toPackageNames = new String[_fromPackages.size() * 2];

        addPatterns('.', 0);
        addPatterns('/', _fromPackages.size());
    }

    void addPatterns(char sep, int off) {
        for (int i = 0; i < _fromPackages.size(); i++) {
            List<String> from = _fromPackages.get(i);
            List<String> to = _toPackages.get(i);

            String pattern = "";

            for (int j = 0; j < from.size(); j++) {
                if (j > 0) {
                    pattern += "\\" + sep;
                }

                pattern += from.get(j);
            }

            String toPackage = "";

            for (int j = 0; j < to.size(); j++) {
                if (j > 0) {
                    toPackage += sep;
                }

                toPackage += to.get(j);
            }

            _fromMatchers[off + i] = Pattern.compile(pattern).matcher("");
            _toPackageNames[off + i] = toPackage;
        }
    }

    public StringBuffer repackage(StringBuffer sb) {
        StringBuffer result = null;

        for (int i = 0; i < _fromMatchers.length; i++) {
            Matcher m = _fromMatchers[i];

            m.reset(sb);

            for (boolean found = m.find(); found; found = m.find()) {
                if (result == null) {
                    result = new StringBuffer();
                }

                m.appendReplacement(result, _toPackageNames[i]);
            }

            if (result != null) {
                m.appendTail(result);
                sb = result;
                result = null;
            }
        }

        return sb;
    }

    public List<List<String>> getFromPackages() {
        return _fromPackages;
    }

    public List<List<String>> getToPackages() {
        return _toPackages;
    }

    public static List<String> splitPath(String path, char separator) {
        ArrayList<String> components = new ArrayList<>();

        for (; ; ) {
            int i = path.indexOf(separator);

            if (i < 0) {
                break;
            }

            components.add(path.substring(0, i));

            path = path.substring(i + 1);
        }

        if (path.length() > 0) {
            components.add(path);
        }

        return components;
    }

    public static String dirForPath(String path) {
        return new File(path).getParent();
    }
}