/*
 * 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:
//     Mike Norman - from Proof-of-concept, become production code
package dbws.testing.shadowddlgeneration.oldjpub;

//javase imports
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

//EclipseLink imports
import dbws.testing.shadowddlgeneration.oldjpub.PublisherException;
import dbws.testing.shadowddlgeneration.oldjpub.Util;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.IS_TYPE_OR_PACKAGE;

/**
 * DML or Query Method
 */
public abstract class SqlStmtMethod extends ProcedureMethod {

    protected String[] m_sqlStmtParamNames;
    protected TypeClass[] m_sqlStmtParamTypes;
    protected int[] m_sqlStmtParamModes;
    protected String m_sqlStmt; // ? represents host variables
    protected String m_sqlStmtTmp;
    protected String m_sqlStmtQuoted;
    protected SqlReflector m_reflector;

    public SqlStmtMethod(String name, int modifiers, String sqlStmt, SqlReflector reflector)
        throws SQLException, PublisherException {
        super(name, null, /* overloadNumber */
        modifiers, null, /* returnType */
        null, /* sqlStmtParamTypes */
        null, /* sqlStmtParamNames */
        null, /* sqlStmtParamModes */
        null, /* sqlStmtParamDefaults */
        -1);

        m_sqlStmt = sqlStmt;
        m_reflector = reflector;
        m_keepMethodName = true;

        /* get method information, populate m_methods */
        // System.out.println("[SqlStmtType] Method: "+methodName); //D+
        /* get host variable/parameter type information */
        // sqlj/semantics/sql/SimpleCheckerImpl.m4
        // oracle.j2ee.ws.db.sqlrefl.Map#writePredefinedName(sqlTypecode):
        // names[getJavaTypecode(sqlTypecode)]
        // SqlType#m_allTypes: CLOB_TYPE "CLOB", OracleTypes.CLOB
        // This loop accomplishes two tasks:
        // (1) Rewrite sqlStatment in the SQLJ format, e.g.,
        // Pre: sqlStmt = "select * from emp where eno=:{x NUMBER}"
        // Post: sqlStmt = "select * from emp where eno=:x"
        // (2) Reflect on the parameter names and types (sqlStmtParamNames, sqlStmtParamTypes)
        // The refection is done by running the sqlStmt against database.
        // The query used for reflection is sqlStmtTmp, e.g.,
        // select * from emp where eno=?,
        // derived by replacing bind variables. :{Y Z} => ?
        m_sqlStmtTmp = m_sqlStmt;
        ArrayList<String> sqlStmtParamNamesV = new ArrayList<String>();
        ArrayList<TypeClass> sqlStmtParamTypesV = new ArrayList<TypeClass>();
        ArrayList<Integer> sqlStmtParamModesV = new ArrayList<Integer>();
        ArrayList<String> uniqueParamNamesV = new ArrayList<String>();
        ArrayList<TypeClass> uniqueParamTypesV = new ArrayList<TypeClass>();
        ArrayList<Integer> uniqueParamModesV = new ArrayList<Integer>();
        Map<String, String> uniqueHash = new HashMap<String, String>();
        int idx0 = m_sqlStmtTmp.lastIndexOf(":{");
        int idx1 = -1;
        int jdbcParamIdx = 0;
        if (idx0 >= 0) {
            idx1 = m_sqlStmtTmp.indexOf('}', idx0);
        }
        while (idx0 >= 0 && idx1 >= 0) {
            jdbcParamIdx++;
            String sqlStmtTmpTerm = m_sqlStmtTmp.substring(idx0 + ":{".length(), idx1);
            StringTokenizer stnz = new StringTokenizer(sqlStmtTmpTerm);
            boolean unique = true; // 3299079
            if (stnz.countTokens() > 1) {
                String paramName = SqlName.sqlIdToJavaId(stnz.nextToken(), false);
                if (paramName != null) {
                    unique = (uniqueHash.get(paramName) == null);
                }
                uniqueHash.put(paramName, paramName);
                sqlStmtParamNamesV.add(paramName);
                if (unique) {
                    uniqueParamNamesV.add(paramName);
                }
                try {
                    // String schema=null;
                    String typeName = stnz.nextToken();
                    // for types like "double precision"
                    while (stnz.hasMoreTokens()) {
                        typeName += " " + stnz.nextToken();
                    }
                    String schema = null;
                    typeName = typeName.toUpperCase();
                    if (typeName.indexOf('.') > -1
                        && typeName.indexOf('.') < (typeName.length() - 1)) {
                        schema = typeName.substring(0, typeName.indexOf('.'));
                        typeName = typeName.substring(typeName.indexOf('.') + 1);
                    }
                    TypeClass tmpType = m_reflector.addSqlUserType(schema, typeName,
                        IS_TYPE_OR_PACKAGE, false, 0, 0, null);
                    sqlStmtParamTypesV.add(tmpType);
                    if (unique) {
                        uniqueParamTypesV.add(tmpType);
                    }
                }
                catch (PublisherException e) {
                    // e.printStackTrace(); //D+
                    throw new SQLException(e.getMessage());
                }
                sqlStmtParamModesV.add(Integer.valueOf(ProcedureMethod.IN));
                if (unique) {
                    uniqueParamModesV.add(Integer.valueOf(ProcedureMethod.IN));
                }
                m_sqlStmtTmp = m_sqlStmtTmp.substring(0, idx0) + "?"
                    + m_sqlStmtTmp.substring(idx1 + 1);
                m_sqlStmt = m_sqlStmt.substring(0, idx0) + ":" + jdbcParamIdx
                    + m_sqlStmt.substring(idx1 + 1);
            }
            else {
                System.err.println("needParamNameAndType " + sqlStmtTmpTerm);
            }
            idx0 = m_sqlStmtTmp.lastIndexOf(":{");
            if (idx0 >= 0) {
                idx1 = m_sqlStmtTmp.indexOf('}', idx0);
            }
        }
        m_sqlStmtParamNames = new String[sqlStmtParamNamesV.size()];
        m_sqlStmtParamTypes = new TypeClass[sqlStmtParamNamesV.size()];
        m_sqlStmtParamModes = new int[sqlStmtParamNamesV.size()];
        for (int j = 0; j < sqlStmtParamNamesV.size(); j++) {
            int jj = sqlStmtParamNamesV.size() - j - 1;
            m_sqlStmtParamNames[jj] = sqlStmtParamNamesV.get(j);
            m_sqlStmtParamTypes[jj] = sqlStmtParamTypesV.get(j);
            m_sqlStmtParamModes[jj] = sqlStmtParamModesV.get(j).intValue();
        }
        m_paramNames = new String[uniqueParamNamesV.size()];
        m_paramTypes = new TypeClass[uniqueParamNamesV.size()];
        m_paramModes = new int[uniqueParamNamesV.size()];
        for (int j = 0; j < uniqueParamNamesV.size(); j++) {
            int jj = uniqueParamNamesV.size() - j - 1;
            m_paramNames[jj] = uniqueParamNamesV.get(j);
            m_paramTypes[jj] = uniqueParamTypesV.get(j);
            m_paramModes[jj] = uniqueParamModesV.get(j).intValue();
        }
    }

    public String getSqlStmt() {
        return m_sqlStmt;
    }

    public String getSqlStmtQuoted() {
        if (m_sqlStmtQuoted == null) {
            m_sqlStmtQuoted = Util.quote(m_sqlStmt);
        }
        return m_sqlStmtQuoted;
    }

    public String[] getSqlStmtParamNames() {
        return m_sqlStmtParamNames;
    }

    public TypeClass[] getSqlStmtParamTypes() {
        return m_sqlStmtParamTypes;
    }
}
