using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HDF5DotNet;
using System.Collections;
namespace ReadHDF5
{
    /*
     * 2011.2.14 xyj
     * ݼҪУָȺлȡеݼ  ȡָƵݼ
     * 
     */

    //õhdf5ݼݣҪΪint飬floatdouble鱣
    class GetHdf5DataSet
    {
        #region ȡݼ,Ҫintfloatdouble
        private Array _dataSet;
        public Array get_Hdf5DataSet
        {
            get
            {
                return _dataSet;
            }
        }
        
        /// <summary>
        /// õint͵ݼ
        /// </summary>
        /// <param name="fileName"></param>ļƣ·
        /// <param name="GroupName"></param>ݼڵȺ
        /// <param name="DsName"></param>ݼ
        /// <param name="dataSet"></param>Ľݼ
        public void hdf5_getDataSet(string fileName, string GroupName, string DsName, int[, ,] dataSet)
        {
            
            H5FileId fileId = H5F.open(fileName, H5F.OpenMode.ACC_RDONLY);
            H5GroupId groupId = H5G.open(fileId, GroupName);
            H5DataSetId dataSetId = H5D.open(groupId, DsName/*"EV_Emissive"*/);
            H5DataTypeId tid0 = H5D.getType(dataSetId);

            H5DataTypeId tid1 = H5T.enumCreate(tid0);//= new H5DataTypeId(H5T.H5Type.NATIVE_INT);//

            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<int>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));


            H5D.close(dataSetId);
            H5G.close(groupId);
            H5F.close(fileId);
            _dataSet = dataSet;

        }
        /// <summary>
        /// õfloat͵ݼ
        /// </summary>
        /// <param name="fileName"></param>ļƣ·
        /// <param name="GroupName"></param>ݼڵȺ
        /// <param name="DsName"></param>ݼ
        /// <param name="dataSet"></param>float[]ݼ
        public void hdf5_getDataSet(string fileName, string GroupName, string DsName, float[, ,] dataSet)
        {
            H5FileId fileId = H5F.open(fileName, H5F.OpenMode.ACC_RDONLY);
            H5GroupId groupId = H5G.open(fileId, GroupName);
            H5DataSetId dataSetId = H5D.open(groupId, DsName/*"EV_Emissive"*/);
            H5DataTypeId tid1 = new H5DataTypeId(H5T.H5Type.NATIVE_FLOAT);

            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<float>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));


            H5D.close(dataSetId);
            H5G.close(groupId);
            H5F.close(fileId);

        }

        /// <summary>
        /// õdouble͵ݼ
        /// </summary>
        /// <param name="fileName"></param>ļƣ·
        /// <param name="GroupName"></param>ݼڵȺ
        /// <param name="DsName"></param>ݼ
        /// <param name="dataSet"></param>Ľݼdouble[]
        public void hdf5_getDataSet(string fileName, string GroupName, string DsName, double[, ,] dataSet)
        {
            H5FileId fileId = H5F.open(fileName, H5F.OpenMode.ACC_RDONLY);
            H5GroupId groupId = H5G.open(fileId, GroupName);
            H5DataSetId dataSetId = H5D.open(groupId, DsName/*"EV_Emissive"*/);
            H5DataTypeId tid1 = new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE);

            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<double>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));


            H5D.close(dataSetId);
            H5G.close(groupId);
            H5F.close(fileId);

        }


        /// <summary>
        /// õintݼ
        /// </summary>
        /// <param name="fileId"></param>ļid
        /// <param name="groupId"></param>Ⱥid
        /// <param name="dataSetId"></param>ݼid
        /// <param name="dataSet"></param>int͵ݼ
        public void hdf5_getDataSet(H5FileId fileId, H5GroupId groupId, H5DataSetId dataSetId, int[, ,] dataSet)
        {
            H5DataTypeId tid1 = new H5DataTypeId(H5T.H5Type.NATIVE_INT);//
            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<int>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));
            _dataSet = dataSet;
        }

        /// <summary>
        /// õfloatݼ
        /// </summary>
        /// <param name="fileId"></param>ļid
        /// <param name="groupId"></param>Ⱥid
        /// <param name="dataSetId"></param>ݼid
        /// <param name="dataSet"></param>float͵ݼ
        public void hdf5_getDataSet(H5FileId fileId, H5GroupId groupId, H5DataSetId dataSetId, float[, ,] dataSet)
        {
            H5DataTypeId tid1 = new H5DataTypeId(H5T.H5Type.NATIVE_FLOAT);//
            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<float>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));
            _dataSet = dataSet;
            
        }

        /// <summary>
        /// õdoubleݼ
        /// </summary>
        /// <param name="fileId"></param>ļid
        /// <param name="groupId"></param>Ⱥid
        /// <param name="dataSetId"></param>ݼid
        /// <param name="dataSet"></param>double͵ݼ
        public void hdf5_getDataSet(H5FileId fileId, H5GroupId groupId, H5DataSetId dataSetId, double[, ,] dataSet)
        {
            H5DataTypeId tid1 = new H5DataTypeId(H5T.H5Type.NATIVE_DOUBLE);//
            // Read the array back
            H5D.read(dataSetId, tid1,
                new H5Array<double>(dataSet));//(dataSetId, tid1, new H5Array<int>(vlReadBackArray));
            _dataSet = dataSet;
        }
        //---------------------------------------------------------------------------------------------------
        #endregion


        /// <summary>
        /// ȡȺеݼ
        /// </summary>
        /// <param name="filename"></param>ļ
        /// <param name="GroupName"></param>Ⱥ
        /// <returns></returns>
        public string[] getDatasetNames(string filename, string GroupName)
        {

          //  filename = @"D:\FY_data\FY3A_VIRRX_GBAL_L1_20090503_0240_1000M_MS.HDF";

            H5FileId fileId = H5F.open(filename, H5F.OpenMode.ACC_RDONLY);
            H5GroupId groupId = H5G.open(fileId, "/");
            ulong num_objs = H5G.getNumObjects(groupId);
            int num = Convert.ToInt32(num_objs);
            string[] dataNames = new string[num];
            for (int i = 0; i < num; i++)
            {
                string name = H5G.getObjectNameByIndex(groupId, i);
                dataNames[i] = name;
            }

            H5G.close(groupId);
            H5F.close(fileId);
            return dataNames;
        }
   
    }




    /*
     * 2011.2.14 xyj
     * ܣȡȺе  ȡֵ
     * 
     * */
    class Hdf5AttributeData
    {

        Array _array;
        #region //----- ȡȺеattributeNames--------
        /// <summary>
        /// õȺֶFunction used with H5A.iterate
        /// </summary>
        /// <param name="attributeId"></param>
        /// <param name="attributeName"></param>
        /// <param name="info"></param>
        /// <param name="attributeNames"></param>
        /// <returns></returns>
        static H5IterationResult MyH5AFunction(
           H5AttributeId attributeId,
           String attributeName,
           H5AttributeInfo info,
           Object attributeNames)
        {
            // Console.WriteLine("Iteration attribute is {0}", attributeName);
            ArrayList nameList = (ArrayList)attributeNames;
            nameList.Add(attributeName);

            // Returning SUCCESS means that iteration should continue to the 
            // next attribute (if one exists).
            return H5IterationResult.SUCCESS;
        }

        /// <summary>
        /// Ⱥе
        /// </summary>
        /// <param name="dataSetId"></param>Ⱥid
        /// <returns></returns>
        public ArrayList getAttributeNames(H5ObjectWithAttributes dataSetId)
        {
            H5AIterateDelegate attributeDelegate;
            attributeDelegate = MyH5AFunction;
            ArrayList attributeNames = new ArrayList();
            ulong position = 0;
            H5A.iterate(dataSetId, H5IndexType.CRT_ORDER,
                        H5IterationOrder.INCREASING,
                        ref position, attributeDelegate,
                        (object)attributeNames);
            return attributeNames;
        }
        //--------------------------------------------------
        #endregion


        #region ȡֵ
        /// <summary>
        /// õֵ㣬ܵõrankΪ0ֵֵҲûȡ
        /// </summary>
        /// <param name="dataSetId"></param>ΪgroupIDdataSetId
        /// <param name="atrrName"></param>
        public Array  getAttributeValue(H5ObjectWithAttributes dataSetId, string atrrName)
        {
            H5AttributeId attributeId = H5A.openName(dataSetId, atrrName);    //ƵõId
            H5DataTypeId attributeType = H5A.getType(attributeId);            //õ
            H5T.H5TClass tcls = H5T.getClass(attributeType);                  //
            uint size = H5T.getSize(attributeType);

            H5T.H5Type H5type;
            string typeName = tcls.ToString();
            H5DataSpaceId spaceid2 = H5A.getSpace(attributeId);
            ulong[] dimsA = H5S.getSimpleExtentDims(spaceid2);
            int rank = H5S.getSimpleExtentNDims(spaceid2);

            //           object[] readBackRamp = new object[dimsA[0]];
            switch (typeName)
            {
                case "FLOAT":
                    if (size > 4)
                    {
                        H5type = H5T.H5Type.NATIVE_DOUBLE;
                        if (rank == 1)
                        {
                            double[] tmp = new Double[dimsA[0]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<double>(tmp));
                            _array = tmp;
                        }
                        else if (rank == 2)
                        {
                            double[,] tmp = new Double[dimsA[0], dimsA[1]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<double>(tmp));
                            _array = tmp;
                        }
                    }
                    else
                    {
                        H5type = H5T.H5Type.NATIVE_FLOAT;
                        if (rank == 1)
                        {
                            float[] tmp = new float[dimsA[0]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<float>(tmp));
                            _array = tmp;
                        }
                        else if (rank == 2)
                        {
                            float[,] tmp = new float[dimsA[0], dimsA[1]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<float>(tmp));
                            _array = tmp;
                        }

                    }
                    break;
                case "STRING":
                    H5type = H5T.H5Type.C_S1;
                    if (rank == 1)
                    {
                        H5type = H5T.H5Type.C_S1;
                        string[] tmp = new string[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        string[,] tmp = new string[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    break;
                case "INTEGER":
                    H5type = H5T.H5Type.NATIVE_INT;
                    if (rank == 1)
                    {
                        int[] tmp = new int[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<int>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        int[,] tmp = new int[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                          new H5Array<int>(tmp));
                        _array = tmp;
                    }
                    break;
                default:
                    H5type = H5T.H5Type.C_S1;
                    if (rank == 1)
                    {
                        string[] tmp = new string[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        string[,] tmp = new string[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    break;

            }

            H5A.close(attributeId);
            return _array;
        }

        /// <summary>
        /// ȡֵ
        /// </summary>
        /// <param name="dataSetId"></param>Ⱥidݼid
        /// <param name="attributeId"></param>id
        /// <returns></returns>
        public Array getAttributeValue(H5ObjectWithAttributes dataSetId, H5AttributeId attributeId)
        {
            H5DataTypeId attributeType = H5A.getType(attributeId);            //õ
            H5T.H5TClass tcls = H5T.getClass(attributeType);                  //
            uint size = H5T.getSize(attributeType);

            H5T.H5Type H5type;
            string typeName = tcls.ToString();
            H5DataSpaceId spaceid2 = H5A.getSpace(attributeId);
            ulong[] dimsA = H5S.getSimpleExtentDims(spaceid2);
            int rank = H5S.getSimpleExtentNDims(spaceid2);

            //           object[] readBackRamp = new object[dimsA[0]];
            switch (typeName)
            {
                case "FLOAT":
                    if (size > 4)
                    {
                        H5type = H5T.H5Type.NATIVE_DOUBLE;
                        if (rank == 1)
                        {
                            double[] tmp = new Double[dimsA[0]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<double>(tmp));
                            _array = tmp;
                        }
                        else if (rank == 2)
                        {
                            double[,] tmp = new Double[dimsA[0], dimsA[1]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<double>(tmp));
                            _array = tmp;
                        }


                    }
                    else
                    {
                        H5type = H5T.H5Type.NATIVE_FLOAT;
                        if (rank == 1)
                        {
                            float[] tmp = new float[dimsA[0]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<float>(tmp));
                            _array = tmp;
                        }
                        else if (rank == 2)
                        {
                            float[,] tmp = new float[dimsA[0], dimsA[1]];
                            H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<float>(tmp));
                            _array = tmp;
                        }

                    }
                    break;
                case "STRING":
                    H5type = H5T.H5Type.C_S1;
                    if (rank == 1)
                    {
                        H5type = H5T.H5Type.C_S1;
                        string[] tmp = new string[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        string[,] tmp = new string[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    break;
                case "INTEGER":
                    H5type = H5T.H5Type.NATIVE_INT;
                    if (rank == 1)
                    {
                        int[] tmp = new int[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<int>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        int[,] tmp = new int[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                          new H5Array<int>(tmp));
                        _array = tmp;
                    }
                    break;
                default:
                    H5type = H5T.H5Type.C_S1;
                    if (rank == 1)
                    {
                        string[] tmp = new string[dimsA[0]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                             new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    else if (rank == 2)
                    {
                        string[,] tmp = new string[dimsA[0], dimsA[1]];
                        H5A.read(attributeId, new H5DataTypeId(H5type), //ȡֵ
                           new H5Array<string>(tmp));
                        _array = tmp;
                    }
                    break;

            }     
            return _array;
        }
        #endregion

    }


    /*
     * 2011.2.14 xyj
     * ܣȡݼϢάΡݡݼͣintfloatdoublelongȡ
     * 
     */   
     
    /// <summary>
    /// ȡݼϢݼά
    /// </summary>
    class GetHdf5DataSetInfo
    {
        int _rank;
        int _row;
        int _col;
        int _bands;
        string _type;
        /// <summary>
        /// ݼά
        /// </summary>
        public int h5fDataRank
        {
            get
            {
                return this._rank;
            }
        }
        /// <summary>
        /// ݼĿ
        /// </summary>
        public int h5fDataWeight
        {
            get
            {
                return this._col;
            }
        }
       /// <summary>
       /// ݾĸ߼
       /// </summary>
        public int h5fDataHeight
        {
            get
            {
                return this._row;
            }
        }
        /// <summary>
        /// ݵͣIntͣfloatͣdouble͵
        /// </summary>
        public string h5fDataType
        {
            get
            {
                return this._type;
            }
        }
        /// <summary>
        /// ݵĲ
        /// </summary>
        public int h5fDataSetBands
        {
            get
            {
                return this._bands;
            }
        }

        //캯
        public GetHdf5DataSetInfo(string fileName, string GroupName, string DsName)
        {
            getH5FDataSetInfo(fileName, GroupName, DsName);
        }
        public GetHdf5DataSetInfo(H5FileId fileId, H5GroupId groupId, H5DataSetId dataSetId)
        {
             getH5FDataSetInfo( fileId,  groupId,  dataSetId);
        }
        /// <summary>
        /// õݼݵϢݼάͣ
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="GroupName"></param>
        /// <param name="DsName"></param>
        public void getH5FDataSetInfo(string fileName, string GroupName, string DsName)
        {
            H5FileId fileId = H5F.open(fileName, H5F.OpenMode.ACC_RDONLY);
            H5GroupId groupId = H5G.open(fileId, GroupName);
            H5DataSetId dataSetId = H5D.open(groupId, DsName);
            //  ulong storeSize = H5D.getStorageSize(dataSetId); //õ洢С
            H5DataSpaceId spaceid = H5D.getSpace(dataSetId);
            ulong[] dims = H5S.getSimpleExtentDims(spaceid);//õĴС[3,1800,2048]
            int rank = H5S.getSimpleExtentNDims(spaceid);//õά3

            _rank = rank;
            int ll = dims.Length;
            if (ll == 2)
            {
                _bands = 1;
                _col = Convert.ToInt32(dims[1]);//
                _row = Convert.ToInt32(dims[0]);
            }
            else if (ll == 3)
            {
                _bands = Convert.ToInt32(dims[0]);//
                _col = Convert.ToInt32(dims[2]);  //
                _row = Convert.ToInt32(dims[1]);  //
            }
            else if (ll == 1)
            {
                _bands = 1;
                _col = 1;
                _row = Convert.ToInt32(dims[0]);//
            }
            else
            {
                _bands = 1;
                _col = 1;
                _row = 1;//
            }
          
            H5DataTypeId dtype = H5D.getType(dataSetId);
            H5T.H5TClass dtcls = H5T.getClass(dtype);//õݼ
            string typeName = dtcls.ToString();
            uint size = H5T.getSize(dtype);


            switch (typeName)
            {
                case "FLOAT":
                    if (size > 4)
                    {
                        _type = "DOUBLE";
                    }
                    else
                    {
                        _type = "FLOAT";
                    }
                    break;

                case "INTEGER":
                    if (size > 4)
                    {
                        _type = "INT64";
                    }
                    else
                    {
                        _type = "INT";
                    }
                    break;

                default:
                    _type = "INT";
                    break;
            }
            H5D.close(dataSetId);
            H5G.close(groupId);
            H5F.close(fileId);
        }

        /// <summary>
        /// õݼݵϢݼάͣ
        /// </summary>
        /// <param name="fileId"></param>ļid
        /// <param name="groupId"></param>Ⱥid
        /// <param name="dataSetId"></param>ݼid
        public void getH5FDataSetInfo(H5FileId fileId, H5GroupId groupId, H5DataSetId dataSetId)
        {           
            H5DataSpaceId spaceid = H5D.getSpace(dataSetId);
            ulong[] dims = H5S.getSimpleExtentDims(spaceid);//õĴС[3,1800,2048]
            int rank = H5S.getSimpleExtentNDims(spaceid);//õά3

            _rank = rank;
            int ll = dims.Length;
            if (ll == 2)
            {
                _bands = 1;
                _col =Convert.ToInt32( dims[0]);
                _row = Convert.ToInt32(dims[1]);
            }
            else if (ll == 3)
            {
                _bands = Convert.ToInt32(dims[0]);
                _col =Convert.ToInt32( dims[1]);
                _row = Convert.ToInt32(dims[2]);
            }
            else if (ll == 1)
            {
                _bands = 1;
                _col = 1;
                _row = Convert.ToInt32(dims[0]);//
            }
            else
            {
                _bands = 1;
                _col = 1;
                _row = 1;
            }

            H5DataTypeId dtype = H5D.getType(dataSetId);
            H5T.H5TClass dtcls = H5T.getClass(dtype);//õݼ
            string typeName = dtcls.ToString();
            uint size = H5T.getSize(dtype);


            switch (typeName)
            {
                case "FLOAT":
                    if (size > 4)
                    {
                        _type = "DOUBLE";
                    }
                    else
                    {
                        _type = "FLOAT";
                    }
                    break;

                case "INTEGER":
                    if (size > 4)
                    {
                        _type = "INT64";
                    }
                    else
                    {
                        _type = "INT";
                    }
                    break;

                default:
                    _type = "INT";
                    break;
            }
     
        }

    }

}