/*
 * 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.Iterator;
import java.util.List;
import java.util.Map;

//EclipseLink imports
import dbws.testing.shadowddlgeneration.oldjpub.MethodFilter;
import dbws.testing.shadowddlgeneration.oldjpub.Util;
import dbws.testing.shadowddlgeneration.oldjpub.FieldInfo;
import dbws.testing.shadowddlgeneration.oldjpub.MethodInfo;
import dbws.testing.shadowddlgeneration.oldjpub.ParamInfo;
import dbws.testing.shadowddlgeneration.oldjpub.ResultInfo;
import dbws.testing.shadowddlgeneration.oldjpub.UserArguments;
import dbws.testing.shadowddlgeneration.oldjpub.ViewCache;
import dbws.testing.shadowddlgeneration.oldjpub.ViewRow;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.ALL_ARGUMENTS;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.DATA_LEVEL;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.OBJECT_NAME;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.OWNER;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.PACKAGE_NAME;
import static dbws.testing.shadowddlgeneration.oldjpub.Util.POSITION;

public class SqlPackageType extends SqlTypeWithMethods {

    protected String m_synonymOwner;
    protected String m_synonymName;
    protected String[] m_executeNames;
    protected ParamInfoValues m_paramInfoValues;

    @Override
    public boolean isPackage() {
        return true;
    }

    public SqlPackageType(SqlName sqlName, SqlType parentType, MethodFilter signatureFilter,
        SqlReflector reflector) throws SQLException {
        super(sqlName, OracleTypes.PACKAGE, true, parentType, signatureFilter, reflector);
        //initSecurityAttributes(sqlName);
    }

    public SqlPackageType(SqlName sqlName, List<ProcedureMethod> methods, SqlReflector reflector)
        throws SQLException {
        super(sqlName, OracleTypes.PACKAGE, true, null, null, reflector);
        m_methods = methods;
        //initSecurityAttributes(sqlName);
    }

    @Override
    protected List<FieldInfo> getFieldInfo() {
        return null;
    }

    public String getSynonymName() {
        return m_synonymName;
    }

    public String[] getExecuteNames() {
        return m_executeNames;
    }

    public boolean hasSecurityAttributes() {
        return m_synonymName != null || m_executeNames.length > 0;
    }

    /*
    protected void initSecurityAttributes(SqlName sqlName) throws SQLException {
        String owner = sqlName.getContextName();
        String name = sqlName.getTypeName();
        // ("SELECT OWNER, SYNONYM_NAME FROM ALL_SYNONYMS WHERE TABLE_OWNER=:1 AND TABLE_NAME=:2");
        Iterator<ViewRow> iter = m_viewCache.getRows(ALL_SYNONYMS, new String[0], new String[]{
            TABLE_OWNER, TABLE_NAME}, new Object[]{owner, name}, new String[0]);
        if (iter.hasNext()) {
            AllSynonyms row = (AllSynonyms)iter.next();
            m_synonymOwner = row.OWNER;
            m_synonymName = row.SYNONYM_NAME;
        }
        // ("SELECT GRANTEE FROM ALL_TAB_PRIVS WHERE TABLE_SCHEMA=:1 AND TABLE_NAME=:2 AND PRIVILEGE='EXECUTE'");
        iter = m_viewCache.getRows(ALL_TAB_PRIVS, new String[]{GRANTEE}, new String[]{TABLE_SCHEMA,
            TABLE_NAME, PRIVILEGE}, new Object[]{owner, name, "EXECUTE"}, new String[0]);
        ArrayList<String> al = new ArrayList<String>();
        while (iter.hasNext()) {
            SingleColumnViewRow row = (SingleColumnViewRow)iter.next();
            al.add(row.getValue());
        }
        m_executeNames = al.toArray(new String[al.size()]);
    }
    */

    @Override
    protected MethodInfo[] getMethodInfo(String schema, String name) throws SQLException {
        /*
         * POSITION of Nth argument is N SEQUENCE of Nth argument is >= N POSITION of function
         * result is 0 SEQUENCE of function result is 1 Special case: If there are no arguments or
         * function results, a row appears anyway, with POSITION=1, SEQUENCE=0.
         *
         * All of which explains the rather strange query below. #sql smi = {SELECT OBJECT_NAME AS
         * METHOD_NAME, OVERLOAD AS METHOD_NO, 'PUBLIC' AS METHOD_TYPE, NVL(MAX(DECODE(SEQUENCE, 0,
         * 0, POSITION)), 0) AS PARAMETERS, NVL(MAX(1-POSITION), 0) AS RESULTS FROM ALL_ARGUMENTS
         * WHERE OWNER = :schema AND PACKAGE_NAME = :name AND DATA_LEVEL = 0 group by OBJECT_NAME,
         * OVERLOAD};
         */
        String[] keys = null;
        Object[] values = null;
        if (m_methodFilter != null && m_methodFilter.isSingleMethod()) {
            keys = new String[]{OWNER, PACKAGE_NAME, OBJECT_NAME, DATA_LEVEL};
            values = new Object[]{schema, name, m_methodFilter.getSingleMethodName(),
                    0};
        }
        else {
            keys = new String[]{OWNER, Util.PACKAGE_NAME, Util.DATA_LEVEL};
            values = new Object[]{schema, name, 0};
        }
        Iterator<ViewRow> iter = m_viewCache.getRows(ALL_ARGUMENTS, new String[0], keys, values,
            new String[0]);
        MethodInfo[] minfo = MethodInfo.groupBy(iter);
        return minfo;
    }

    @Override
    protected ResultInfo getResultInfo(String schema, String name, String methodName,
                                       String methodNo) throws SQLException {
        if (m_resultInfoValues == null || !m_resultInfoValues.matches(schema, name)) {
            m_resultInfoValues = new ResultInfoValues(schema, name, m_methodFilter, m_viewCache);
        }
        return m_resultInfoValues.get(methodName, methodNo);
    }

    private ResultInfoValues m_resultInfoValues;

    private static class ResultInfoValues extends InfoValues {
        public ResultInfoValues(String schema, String name, MethodFilter methodFilter,
            ViewCache viewCache) throws SQLException {
            super(schema, name);
            String[] keys = null;
            Object[] values = null;
            if (methodFilter != null && methodFilter.isSingleMethod()) {
                keys = new String[]{OWNER, PACKAGE_NAME, OBJECT_NAME,
                    DATA_LEVEL, POSITION};
                values = new Object[]{schema, name, methodFilter.getSingleMethodName(),
                        0, 0};
            }
            else {
                keys = new String[]{OWNER, PACKAGE_NAME, DATA_LEVEL, POSITION};
                values = new Object[]{schema, name, 0, 0};
            }

            Iterator<ViewRow> iter = viewCache.getRows(ALL_ARGUMENTS, new String[0], keys, values,
                new String[0]);
            while (iter.hasNext()) {
                UserArguments item = (UserArguments)iter.next();
                String key = makeKey(item.OBJECT_NAME /* METHOD_NAME */, item.OVERLOAD/* METHOD_NO */);
                if (m_ht.get(key) == null) {
                    ArrayList<ViewRow> itemWrapper = new ArrayList<ViewRow>();
                    itemWrapper.add(item);
                    m_ht.put(key, itemWrapper);
                }
            }
        }

        public ResultInfo get(String method_name, String method_no) throws java.sql.SQLException {
            ArrayList<ViewRow> row = m_ht.get(makeKey(method_name, method_no));
            ResultInfo rinfo = null;
            rinfo = new ResultInfo((UserArguments)row.get(0));
            return rinfo;
        }
    }

    @Override
    protected ParamInfo[] getParamInfo(String schema, String name, String methodName,
                                       String methodNo) throws SQLException {
        if (m_paramInfoValues == null || !m_paramInfoValues.matches(schema, name)) {
            m_paramInfoValues = new ParamInfoValues(schema, name, m_methodFilter, m_viewCache);
        }
        return m_paramInfoValues.get(methodName, methodNo);
    }

    private static class InfoValues {
        protected String m_schema;
        protected String m_name;
        protected Map<String, ArrayList<ViewRow>> m_ht;

        public InfoValues(String schema, String name) throws SQLException {
            m_schema = schema;
            m_name = name;
            m_ht = new HashMap<String, ArrayList<ViewRow>>();
        }

        protected static String makeKey(String method, String method_no) {
            return "" + method + "/" + method_no;
        }

        public boolean matches(String schema, String name) {
            return ((schema == null) ? m_schema == null : schema.equals(m_schema))
                && ((name == null) ? m_name != null : name.equals(m_name));
        }
    }
    private static class ParamInfoValues extends InfoValues {
        public ParamInfoValues(String schema, String name, MethodFilter methodFilter,
            ViewCache viewCache) throws SQLException {
            super(schema, name);
            String[] keys = null;
            Object[] values = null;
            if (methodFilter != null && methodFilter.isSingleMethod()) {
                keys = new String[]{OWNER, PACKAGE_NAME, OBJECT_NAME, DATA_LEVEL};
                values = new Object[]{schema, name, methodFilter.getSingleMethodName(),
                        0};
            }
            else {
                keys = new String[]{OWNER, PACKAGE_NAME, DATA_LEVEL};
                values = new Object[]{schema, name, 0};
            }
            Iterator<ViewRow> iter = viewCache.getRows(ALL_ARGUMENTS, new String[0], keys, values,
                new String[0]);
            ArrayList<ViewRow> viewRows = new ArrayList<ViewRow>();
            while (iter.hasNext()) {
                UserArguments item = (UserArguments)iter.next();
                if (item.ARGUMENT_NAME != null) {
                    viewRows.add(item);
                }
            }
            UserArguments.orderByPosition(viewRows);
            for (int i = 0; i < viewRows.size(); i++) {
                UserArguments item = (UserArguments)viewRows.get(i);
                String key = makeKey(item.OBJECT_NAME/* METHOD_NAME */, item.OVERLOAD/* METHOD_NO */);
                ArrayList<ViewRow> v = m_ht.get(key);
                if (v == null) {
                    v = new ArrayList<ViewRow>();
                    m_ht.put(key, v);
                }
                v.add(item);
            }
        }

        public ParamInfo[] get(String method, String method_no) throws SQLException {
            ArrayList<ViewRow> v = m_ht.get(makeKey(method, method_no));
            if (v == null) {
                v = new ArrayList<ViewRow>(); // zero parameter
            }
            return ParamInfo.getParamInfo(v);
        }
    }
}
