package com.sun.solarisinstall.core;

import com.sun.wizards.core.*;
import com.sun.solarisinstall.panels.*;
import java.lang.*;
import java.util.*;
import java.io.*;

/**
 * Dependency  class - taken and adapted from genie
 *
 *    Performs meta-cluster vs. product dependency checking
 *
 */
public class Depend {

  private String MetaClusters[] = {		// Solaris Meta Cluster
                     "SUNWCXall",
                     "SUNWCall",
                     "SUNWCprog",
                     "SUNWCuser",
                     "SUNWCreq",
                      };

  private String ClusterLabel[] = {	// Solaris Meta Cluster
                     "Entire Solaris Software Group Plus OEM",
                     "Entire Solaris Software Group",
                     "Developer Solaris Software Group",
                     "End User Solaris Software Group",
                     "Core Solaris Software Group",
                     };
	
  /*
   * following not currently used
   */
  private Vector DependPkgs = new Vector(); // Auto pkgadd for Profile
  private Vector DependProducts = new Vector(); // Dependent product


  private Vector allProdlist = null; 	
  private Vector selProdlist = null; 	
  private String DependMetaCluster = null; 	
  private int    DependMetaClusterIndex = 99; 	
  private static String ConfigFilePrefix = "pd";
  private static String ClusterNamePrefix = "SUNWC";
  private DependError ErrorInfo = new DependError();
  private int Os = 99;
  private boolean ChkOS = true;
  private boolean upgrade = false;

  // Constructor 
  //
  // Descriptions: 
  // 	Loop thru the prodlist vector
  // 		For each product, find out all metacluster dependency
  //
  // Input Arguments:
  // 	Vector selprodlist - Selected Product list
  // 	Vector allprodlist - All known products 
  //	String osCluster - OS metacluster name (e.g. SUNWCall)
  //
  // Return:
  //	None.
  //
  // Side Effects: 
  // 	DependPkgs is set, DependProducts, ErrorInfo
  //      may be set.
  //
  public Depend(Vector selprodlist, Vector allprodlist, String osCluster){
    this(selprodlist, allprodlist, osCluster, false);
  }

  public Depend(Vector selprodlist, Vector allprodlist, String osCluster, boolean doingUpgrade){
    String 	depend;
    StringTokenizer token = null;

    this.upgrade = doingUpgrade;
    selProdlist = (Vector)selprodlist.clone();
    allProdlist = (Vector)allprodlist.clone();
    if (Def.DEBUG) System.out.println();
    for (int i = 0; i < selProdlist.size(); i++) {
      String fname = ((SolarisProduct)selProdlist.elementAt(i)).getFilename();
    }
    Os = lookupCluster(osCluster);
      if (Def.DEBUG) System.out.println("Depend: Os="+getOSCluster());
    chkDepend();
  }

  private void chkDepend() {
    String prodName;
    String chkstr;
    String depend;
    StringTokenizer token = null;
    int RequiredOS = 99;

    ErrorInfo.reset();

    for (int i = 0; i < selProdlist.size(); i++) {
      depend = ((SolarisProduct)selProdlist.elementAt(i)).getDepend();
      SolarisProduct pd = (SolarisProduct)selProdlist.elementAt(i);
      prodName = ((SolarisProduct)selProdlist.elementAt(i)).getName();
      if (Def.DEBUG) {
        String fname = ((SolarisProduct)selProdlist.elementAt(i)).getFilename();
        System.out.print("chkDepend: product: "+fname);
      } 
      if (depend == null) {
        if (Def.DEBUG) System.out.println(" ==> NO depend");
        continue;
      } else if (Def.DEBUG) System.out.println(" ==> "+depend);

      int curReqOS = 99;
      int minReqOS = 99;
      token = new StringTokenizer(depend);
      while ( token.hasMoreTokens() ) {
        chkstr = token.nextToken();
        curReqOS = processToken(chkstr,prodName);
        if (ErrorInfo.hasError()) {
          if (!ChkOS) {
            return;
          } else if (curReqOS < minReqOS) {
            minReqOS = curReqOS;
            if (minReqOS < RequiredOS) {
              RequiredOS = minReqOS;
            }
          }
        }
      }

      //if (ErrorInfo.hasError() && ChkOS && minReqOS < ClusterLabel.length) {
      if (ErrorInfo.hasError() && ChkOS && RequiredOS < ClusterLabel.length) {
        //ErrorInfo.setInfoAt((Object) ClusterLabel[minReqOS], 0);
        ErrorInfo.setInfoAt((Object) MetaClusters[RequiredOS], 0);
      }
    }

    return;
  }
	
  private int processToken(String str, String prodName) {

    int index = str.indexOf('.');
    if (index <=  0 ) {
      if ( str.startsWith(ClusterNamePrefix) ) {
        int prod =lookupCluster(str);
        /*
         * It's a metacluster 
         */
        if ( prod >= 0 ) {
          /*
           * Verify metacluster selection
           */
          if ( prod < Os && ChkOS ) {
            if (upgrade) {
              if (Def.DEBUG) {
                 System.out.println("processToken setting OS_NOT_VALID_UPGRADE"
                                    + " prod=" + prod + " Os="+Os );
              }
              ErrorInfo.setErrorCode (DependError.OS_NOT_VALID_UPGRADE);
            } else {
              if (Def.DEBUG) {
                 System.out.println("processToken setting OS_NOT_VALID prod=" 
                                    + prod + " Os="+Os );
              }
              ErrorInfo.setErrorCode (DependError.OS_NOT_VALID);
            }
            if (ErrorInfo.getInfoSize() == 0) {
              ErrorInfo.appendInfo((Object) ClusterLabel[prod]);
              ErrorInfo.appendInfo((Object) ClusterLabel[Os]);
            }
          ErrorInfo.appendInfo ((Object) prodName);

            return prod;
          }

/*
          if ( prod < Os && !ChkOS ) {
            ErrorInfo.setErrorCode(DependError.PROD_NEEDS_MORE_OS);
            ErrorInfo.appendInfo((Object)ClusterLabel[prod]);
            ErrorInfo.appendInfo((Object)ClusterLabel[Os]); 
            ErrorInfo.appendInfo((Object)prodName);
            return prod;
          }
*/
          // Selected metacluster is smaller set
          // of required cluster
          if (prod < DependMetaClusterIndex) {
            DependMetaClusterIndex = prod;
          }
        } 
        return DependMetaClusterIndex;
      }
/*
      // It is a package dependency
      DependProducts.addElement(str);
*/
    } else {
/*
      // It is a product dependency

      String chkstr = str.substring(0,index);
      if (chkstr.compareTo(ConfigFilePrefix) == 0) {
        // Check if the product is selected?
        if ( !isSelected(str) ) {
          DependProducts.addElement(str);
          ErrorInfo.setErrorCode(DependError.MISSING_PROD_DEPEND);
          //ErrorInfo.appendInfo((Object)prodName);
          ErrorInfo.appendInfo((Object)getProdName(str));
          return DependMetaClusterIndex;
        } 
      } 
*/
    }
    return DependMetaClusterIndex;
  }

  private int lookupCluster(String cluster) {
    for (int i = 0; i < MetaClusters.length; i++) {
      if ( (MetaClusters[i].compareTo(cluster)) == 0) {
        return i;
      }
    }
    // Not found
    return -1;
  }

  private boolean isSelected(String pdfile) {
    for (int i = 0; i < selProdlist.size(); i++) {
      SolarisProduct prod = (SolarisProduct) selProdlist.elementAt(i);
      if (prod.file.compareTo(pdfile) == 0) {
        return true;
      }
    }
    return false;
  }

  private boolean isExist(Vector exist, String check) {
    for (int i = 0; i < exist.size(); i++) {
      if (((String)exist.elementAt(i)).compareTo(check) == 0){
        return true;
      }
    }
    return false;
  }
	
  private String getProdName(String fname) {
    for (int i=0; i < allProdlist.size(); i++) {
      SolarisProduct p = (SolarisProduct) allProdlist.elementAt(i);
      if (p.file.equals(fname)) {
        return p.getName();
      }
    }
    return null;
  }


  //  Accessor method for getting Depend's product list.
  public Vector getSelProductList() {
    return selProdlist;
  }


  //  Accessor method for getting Depend's OS cluster.
  public String getOSCluster() {
    return (MetaClusters[Os]);
  }

  public DependError getDependError() {
    return ErrorInfo;
  }

  public Vector getDependPkgs() {
    return DependPkgs;
  }

  public Vector getDependProducts() {
    return DependProducts;
  }

  public String getDependMetaCluster() {
    return MetaClusters[DependMetaClusterIndex];
  }

  public DependError updateOS(String osCluster ) {
    if (Def.DEBUG) System.out.println("\nDepend in updateOS "+osCluster);
    ErrorInfo = new DependError();
    
    /*
     *  Modified the cluster 
     */
    ChkOS = true;
    int saveOs = Os;
    Os = lookupCluster(osCluster);
    chkDepend();
    if (ErrorInfo.hasError()) {
      Os = saveOs;
    }
    return ErrorInfo;
  }


  public DependError addProduct(SolarisProduct p) {
    ErrorInfo = new DependError();
    // Add to the product list
    selProdlist.addElement(p);
    for (int i = 0; i < selProdlist.size(); i++) {
      SolarisProduct prod = (SolarisProduct) selProdlist.elementAt(i);
    }
    ChkOS = false;
    chkDepend();
    if (ErrorInfo.hasError()) {
      //selProdlist.removeElement(p);
      for (int i = 0; i < selProdlist.size(); i++) {
        SolarisProduct prod = (SolarisProduct) selProdlist.elementAt(i);
        if (prod.file.compareTo(p.file) == 0) {
          selProdlist.removeElementAt(i);
          break;
        }
      }
    }
    return ErrorInfo;
  }


  public DependError deleteProduct(SolarisProduct p) {
    ErrorInfo = new DependError();

    // Delete the product from product list
    SolarisProduct saveP = null;
    for (int i = 0; i < selProdlist.size(); i++) {
      SolarisProduct prod = (SolarisProduct) selProdlist.elementAt(i);
      if (prod.file.compareTo(p.file) == 0) {
        saveP = prod;
        selProdlist.removeElementAt(i);
        break;
      }
    }
    ChkOS = false;
    chkDepend();
    if (ErrorInfo.hasError()) {
      selProdlist.addElement(saveP);
    }
    return ErrorInfo;
  }

}
