
import java.util.logging.Logger;

// mySQL access
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import java.sql.Array;
// import javax.sql.*; needed if using DataSource instead of DriverManager for DB-connections

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;

import java.util.Enumeration;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;
import java.util.HashSet;
import java.util.ArrayList;

import java.lang.ClassNotFoundException;



public class AuthPolicyDb
{
   private static final Logger LOGGER = Logger.getLogger(AuthPolicyDb.class.getName());

   private static final AuthZSettings settings = AuthZSettings.getInstance("authpolicy.properties");
   private static final AuthZSettings.DBConn dbconn = settings.dbConn;


   public class PubdidGroups
   {
      String pubdid;
      String[] groups;
      PubdidGroups(String pubdid, String[] groups)
      {
         this.pubdid = pubdid;
         this.groups = groups;
      }
   }


   public List<PubdidGroups> queryGroupsPrivateOnly(Set<String> uniqPubdids)
   {
      Set<String> uniqObscorePubdids = uniqPubdids;
      String commaSepObscorePubdids  = String.join("\',\'", uniqObscorePubdids);

      assert (commaSepObscorePubdids != null) && (!commaSepObscorePubdids.isEmpty());

      String TheQuery = "SELECT obs_publisher_did,groups FROM obscore "
         + "WHERE (policy = 'PRIV') AND (obs_publisher_did IN (\'"+commaSepObscorePubdids+"\'));";

      LOGGER.finer("Connecting to: "+dbconn.uri()+" with optional user/pwd: "+dbconn.userName()+" / ***");

      List<PubdidGroups> pubdidGroups = new LinkedList<PubdidGroups>();

      try(Connection conn = DriverManager.getConnection(dbconn.uri(), dbconn.userName(), dbconn.password());
            Statement  st   = conn.createStatement();
            ResultSet  res  = st.executeQuery(TheQuery);)
      {
         while (res.next())
         {
            String pubdid   = res.getString("obs_publisher_did");
            Array groupsArr = res.getArray("groups");

            String[] groups = null;
            if(groupsArr == null)
               groups = null;
            else
               groups = (String[]) groupsArr.getArray();

            PubdidGroups pg = new PubdidGroups(pubdid, groups);
            pubdidGroups.add(pg); 
         }
      }
      catch (SQLException se)
      {
         logSqlExInfo(se);
         se.printStackTrace();
      }

      return pubdidGroups; 
   }



   public List<String> selectPublicOnly(String[] uniqPubdids)
   {
      String commaSepObscorePubdids  = String.join("\',\'", uniqPubdids);

      assert (commaSepObscorePubdids != null) && (!commaSepObscorePubdids.isEmpty());

      String TheQuery
         = "SELECT obs_publisher_did FROM obscore "
         + "WHERE (policy = 'FREE') AND (obs_publisher_did IN (\'"+commaSepObscorePubdids+"\'));";

      LOGGER.finer("Connecting to: "+dbconn.uri()+" with optional user/pwd: "+dbconn.userName()+" / ***");

      List<String> pubdidPublic = new LinkedList<String>();

      try(Connection conn  = DriverManager.getConnection(dbconn.uri(), dbconn.userName(), dbconn.password());
            Statement  st  = conn.createStatement();
            ResultSet  res = st.executeQuery(TheQuery);)
      {
         while (res.next())
         {
            pubdidPublic.add(res.getString("obs_publisher_did")); 
         }
      }
      catch (SQLException se)
      {
         logSqlExInfo(se);
         se.printStackTrace();
      }

      LOGGER.finest("Found public: " + pubdidPublic.size());

      return pubdidPublic; 
   }





   private void logSqlExInfo(SQLException se)
   {
      LOGGER.severe("SQLState : " + se.getSQLState());
      LOGGER.severe("ErrorCode: " + se.getErrorCode());
      LOGGER.severe("Message  : " + se.getMessage());
      Throwable t = se.getCause();
      while(t != null) {
         LOGGER.severe("Cause: " + t);
         t = t.getCause();
      }
   }

}

