/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.codegen;

import java.util.*;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: Model a method for code generation purposes.
 *
 * @since TopLink 3.0
 * @author James Sutherland
 */
public abstract class MethodDefinition extends CodeDefinition {
    protected boolean isAbstract;
    protected boolean isConstructor;
    protected String returnType;
    protected Vector<String> argumentNames;
    protected Vector<String> lines;
    protected Vector<String> exceptions;
    protected StringBuffer storedBuffer;

    protected MethodDefinition() {
        this.isConstructor = false;
        this.returnType = "void";
        this.lines = new Vector<>();
        this.exceptions = new Vector<>();
        this.storedBuffer = new StringBuffer();
    }

    public void addException(String exceptionTypeName) {
        this.exceptions.add(exceptionTypeName);
    }

    public void addLine(String line) {
        this.storedBuffer.append(line);
        getLines().addElement(this.storedBuffer.toString());
        this.storedBuffer = new StringBuffer();
    }

    /**
     * This method can be used to store a string that will be prepended to the very next line of code entered
     */
    public void addToBuffer(String partOfLine) {
        this.storedBuffer.append(partOfLine);
    }

    private void adjustExceptions(Map<String, Set<String>> typeNameMap) {
        for (Iterator<String> i = new Vector<>(getExceptions()).iterator(); i.hasNext();) {
            String exceptionName = i.next();
            String adjustedExceptionName = adjustTypeName(exceptionName, typeNameMap);

            if (!exceptionName.equals(adjustedExceptionName)) {
                replaceException(exceptionName, adjustedExceptionName);
            }
        }
    }

    /**
     * Parses the line, removing the package name for each type
     * (and adding the appropriate import) if the type is
     * unambiguous.
     */
    private void adjustLine(String line, Map<String, Set<String>> typeNameMap) {
        StringBuilder lineInProgress = new StringBuilder(line);
        Set<String> typeNames = parseForTypeNames(lineInProgress.toString());

        for (Iterator<String> i = typeNames.iterator(); i.hasNext();) {
            String typeName = i.next();
            String adjustedTypeName = adjustTypeName(typeName, typeNameMap);

            if (!typeName.equals(adjustedTypeName)) {
                int typeNameStartIndex = lineInProgress.toString().indexOf(typeName);

                while (typeNameStartIndex != -1) {
                    lineInProgress.replace(typeNameStartIndex, typeNameStartIndex + typeName.length(), adjustedTypeName);
                    typeNameStartIndex = lineInProgress.toString().indexOf(typeName);
                }
            }
        }

        replaceLine(line, lineInProgress.toString());
    }

    private void adjustLines(Map<String, Set<String>> typeNameMap) {
        for (Iterator<String> i = new Vector<>(getLines()).iterator(); i.hasNext();) {
            adjustLine(i.next(), typeNameMap);
        }
    }

    private void adjustReturnType(Map<String, Set<String>> typeNameMap) {
        String adjustedReturnType = adjustTypeName(getReturnType(), typeNameMap);

        if (!getReturnType().equals(adjustedReturnType)) {
            setReturnType(adjustedReturnType);
        }
    }

    protected void adjustTypeNames(Map<String, Set<String>> typeNameMap) {
        adjustReturnType(typeNameMap);
        adjustExceptions(typeNameMap);
        adjustLines(typeNameMap);
    }

    protected abstract boolean argumentsEqual(MethodDefinition methodDefinition);

    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }

        if (!(object instanceof MethodDefinition)) {
            return false;
        }

        MethodDefinition methodDefinition = (MethodDefinition)object;

        if ((this.name == null) && (methodDefinition.getName() != null)) {
            return false;
        }
        if ((this.name != null) && !this.name.equals(methodDefinition.getName())) {
            return false;
        }

        if (!this.accessLevel.equals(methodDefinition.getAccessLevel())) {
            return false;
        }

        if (!this.returnType.equals(methodDefinition.getReturnType())) {
            return false;
        }

        if (!argumentsEqual(methodDefinition)) {
            return false;
        }

        if (!exceptionsEqual(methodDefinition)) {
            return false;
        }

        return true;
    }

    protected boolean exceptionsEqual(MethodDefinition methodDefinition) {
        Object[] exceptions1 = this.getExceptions().toArray();
        Object[] exceptions2 = methodDefinition.getExceptions().toArray();
        if (exceptions1.length == exceptions2.length) {
            for (int i = 0; i < exceptions1.length; i++) {
                if (((exceptions1[i] == null) && (exceptions1[i] != exceptions2[i])) || (!exceptions1[i].equals(exceptions2[i]))) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    protected Vector<String> getArgumentNames() {
        if (this.argumentNames == null) {
            this.argumentNames = new Vector<>(5);
        }
        return argumentNames;
    }

    public String getArgumentName(int index) {
        return getArgumentNames().get(index);
    }

    public Iterator<String> argumentNames() {
        return getArgumentNames().iterator();
    }

    public int argumentNamesSize() {
        return getArgumentNames().size();
    }

    protected abstract Vector<String> getArgumentTypeNames();

    protected abstract Vector<String> getArgumentTypes();

    public Vector<String> getLines() {
        return lines;
    }

    protected Vector<String> getExceptions() {
        return this.exceptions;
    }

    public String getReturnType() {
        return returnType;
    }

    @Override
    public int hashCode() {
        int hash = this.accessLevel.hashCode();
        hash ^= this.returnType.hashCode();
        hash ^= this.getArgumentTypes().hashCode();

        if (this.name != null) {
            hash ^= this.name.hashCode();
        }

        if (this.name != null) {
            hash ^= this.name.hashCode();
        }

        hash ^= this.getExceptions().hashCode();

        return hash;
    }

    public boolean isAbstract() {
        return this.isAbstract;
    }

    public boolean isConstructor() {
        return isConstructor;
    }

    /**
     * Used for calculating imports.  @see org.eclipse.persistence.internal.codegen.ClassDefinition#calculateImports()
     */
    protected void putTypeNamesInMap(Map<String, Set<String>> typeNameMap) {
        putTypeNameInMap(getReturnType(), typeNameMap);

        for (Iterator<String> i = getExceptions().iterator(); i.hasNext();) {
            putTypeNameInMap(i.next(), typeNameMap);
        }

        for (Iterator<String> i = getArgumentTypeNames().iterator(); i.hasNext();) {
            putTypeNameInMap(i.next(), typeNameMap);
        }
    }

    protected void replaceException(String oldExceptionName, String newExceptionName) {
        int index = getExceptions().indexOf(oldExceptionName);
        getExceptions().remove(oldExceptionName);
        getExceptions().insertElementAt(newExceptionName, index);
    }

    protected void replaceLine(String oldLine, String newLine) {
        int index = getLines().indexOf(oldLine);
        getLines().remove(oldLine);
        getLines().insertElementAt(newLine, index);
    }

    public void setIsAbstract(boolean isAbstract) {
        this.isAbstract = isAbstract;
    }

    public void setIsConstructor(boolean isConstructor) {
        this.isConstructor = isConstructor;
    }

    public void setReturnType(String returnType) {
        this.returnType = returnType;
    }

    /**
     * Write the code out to the generator's stream.
     */
    @Override
    public void writeBody(CodeGenerator generator) {
        if (!isConstructor()) {
            generator.writeType(getReturnType());
            generator.write(" ");
        }
        generator.write(getName());
        generator.write("(");

        writeArguments(generator);

        generator.write(")");

        if (!this.exceptions.isEmpty()) {
            writeThrowsClause(generator);
        }

        if (isAbstract()) {
            generator.write(";");
        } else {
            generator.write(" {");

            generator.cr();

            for (Enumeration<String> linesEnum = getLines().elements(); linesEnum.hasMoreElements();) {
                generator.tab();
                generator.writeln(linesEnum.nextElement());
            }

            generator.write("}");
        }
    }

    protected abstract void writeArguments(CodeGenerator generator);

    protected void writeThrowsClause(CodeGenerator generator) {
        generator.write(" throws ");

        for (Iterator<String> exceptionIterator = this.exceptions.iterator(); exceptionIterator.hasNext();) {
            generator.write(exceptionIterator.next());

            if (exceptionIterator.hasNext()) {
                generator.write(", ");
            }
        }
    }
}
