/*****************************************************************************e
*
*  NSSDC/CDF                      Quick Start Test Program(C# interface).
*
*  Version 1.0,15-Oct-09,Mike Liu
*
*  Modification history:
*
*   V1.0   15-Oct-09,M Liu     Original version(for CDF V3.3).
*                              Using pointers (&) to pass arguments for 
*                              retrieving data fields and values to C# APIs.
*
******************************************************************************/

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Text;

using CDF;

public class QstReadCDF : CDFAPIs {

unsafe public static void Main(string[] args) {
  void* id;
  int status;

id = (void *) 0;
try {
  status = CDFopen(args[0],&id);
  Dictionary<string,object> cdf = ReadCDF(id);
  foreach (KeyValuePair<string,object> pair in cdf) {
///Console.WriteLine("key="+pair.Key);
    /// May contain 3 key/value pairs: keys include "CDFinfo",
    /// "GlobalAttributes" and "Variables".
    ///
    /// Get key: "Variables"'s value -- a Dictionary
    if (String.Compare(pair.Key,"Variables") == 0) {
	Console.WriteLine("Variables:");
        Dictionary<string,object> vars = (Dictionary<string,object>) pair.Value;
        if (vars == null) continue;
        foreach (KeyValuePair<string,object> pair1 in vars) {
        /// each key-value pair is variable name and its info
            Console.WriteLine(" ** Variable: "+pair1.Key);
            Dictionary<string,object> var = (Dictionary<string,object>) pair1.Value;
            /// Each variable's info includes upto 3 key/value mappings:
            /// "VarInfo", "VarMetaData" and "VarData".
            foreach (KeyValuePair<string,object> pair2 in var) {
                if (String.Compare(pair2.Key,"VarInfo") == 0) {
		    Console.WriteLine("  ===> VarInfo:");
                    /// Key: "VarInfo" has Variable specification
                    Dictionary<string,object> specs = (Dictionary<string,object>) pair2.Value;
                    foreach (KeyValuePair<string,object> pair3 in specs) {
                        ///Console.WriteLine(pair3.Key+" => "+pair3.Value);
                        Console.Write("    "+pair3.Key+" => ");
			CDFUtils.PrintValue(pair3.Value);
                    }
                } else if (String.Compare(pair2.Key,"VarMetaData") == 0) {
		    Console.WriteLine("  ===> VarMetaData:");
                    /// Key: "VarMeataData" has variable metadata
                    Dictionary<string,object> meta = (Dictionary<string,object>) pair2.Value;
                    foreach (KeyValuePair<string,object> pair3 in meta) {
                        ///Console.WriteLine(pair3.Key+" => "+pair3.Value);
                        Console.Write("    "+pair3.Key+" => ");
			CDFUtils.PrintValue(pair3.Value);
                    }
                } else if (String.Compare(pair2.Key,"VarData") == 0) {
		    Console.WriteLine("  ===> VarData:");
                    /// Key: "VarData" has variable data
                    object data = (object) pair2.Value;
                    /// Console.Write(" data="+data);
		    /// CDFUtils.DumpObject (data);
		    CDFUtils.PrintValue(data);
                } else {
                    Console.WriteLine("error.... for key: "+pair2.Key);
	        }
            }
        }
    } else if (String.Compare(pair.Key,"CDFInfo") == 0) {
	Console.WriteLine("CDFInfo:");
        Dictionary<string,object> info = (Dictionary<string,object>) pair.Value;
        if (info == null) continue;
        foreach (KeyValuePair<string,object> pair1 in info) {
           /// each key-value pair is variable name and its info
           Console.Write("    "+pair1.Key+" => ");
	   CDFUtils.PrintValue(pair1.Value);
	}
    } else if (String.Compare(pair.Key,"GlobalAttributes") == 0) {
	Console.WriteLine("GlobalAttributes:");
        Dictionary<string,object> attrs = (Dictionary<string,object>) pair.Value;
        if (attrs == null) continue;
        foreach (KeyValuePair<string,object> pair1 in attrs) {
        /// each key-value pair is global attribute name and its entries
            Console.WriteLine(" ** Attribute: "+pair1.Key);
            Dictionary<int,object> var = (Dictionary<int,object>) pair1.Value;
            foreach (KeyValuePair<int,object> pair2 in var) {
               Console.Write("    "+pair2.Key+" => ");
	       CDFUtils.PrintValue(pair2.Value);
	    }
        }
    } else if (String.Compare(pair.Key,"NoEntryAttributes") == 0) {
	Console.WriteLine("NoEntryAttributes:");
        Dictionary<string,object> attrs = (Dictionary<string,object>) pair.Value;
        if (attrs == null) continue;
        foreach (KeyValuePair<string,object> pair1 in attrs) {
        /// each key-value pair is a global attributes or variable attributes
	    Console.WriteLine("  ===> "+pair1.Key+":");
            List<string> noattrs = (List<string>) pair1.Value;
	    Console.Write("        ");
	    int yy;
	    yy = 0;
            foreach (string name in noattrs) {
	       ++yy;
	       if (yy > 1) Console.Write(", ");
               Console.Write(name);
	    }
	    Console.WriteLine("");
        }
    }
  }

///  DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<string, object>));

///  using (MemoryStream ms = new MemoryStream()) {
///    serializer.WriteObject(ms, cdf);
///    Console.WriteLine(Encoding.Default.GetString(ms.ToArray()));
///  }

  status = CDFcloseCDF(id);  


/******************************************************************************
* Successful completion.
******************************************************************************/
} catch(CDFException ex) {
  Console.WriteLine("Error... "+ex);
} finally {
  try {
    status = CDFselect(id);
    status = CDFcloseCDF(id);
  } catch(CDFException ex) {}
}

}


/******************************************************************************
* QuitCDF.
******************************************************************************/

unsafe static void QuitCDF(string where, int status, void* id)
{
  string text;
  Console.WriteLine("Aborting at "+where);
  if(status < 0) {
    status = CDFgetStatusText(status,out text); 
    Console.WriteLine(" "+text);
  }
  status = CDFcloseCDF(id);
  Console.WriteLine("...test aborted.");
}

}

