package gov.nasa.worldwind.formats.rpf;

import gov.nasa.worldwind.formats.nitfs.*;
import gov.nasa.worldwind.geom.*;

import java.nio.*;
/*
Copyright (C) 2001, 2007 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/

/**
 * @author lado
 * @version $Id: RpfFrameFileComponents Mar 31, 2007 10:06:22 PM
 */
public class RpfFrameFileComponents 
{
    public static final String DATA_TAG = "RPFIMG";

    // [ rpf location section ]
    public RpfLocationSection componentLocationTable;

    // [ rpf coverage section ]
    public LatLon nwUpperLeft, swLowerleft, neUpperRight, seLowerRight;
    public double verticalResolutionNorthSouth;
    public double horizontalResolutionEastWest;
    public double verticalIntervalLatitude;
    public double horizontalIntervalLongitude;

    // [ color / grayscale section ]
    public RpfColorMap[] rpfColorMaps;

    // [ rpf color / grayscale section ]
    public short numOfColorGrayscaleOffsetRecords;
    public short numOfColorConverterOffsetRecords;
    public String externalColorGrayscaleFilename;
    // [ rpf colormap subsection ]
    public long colormapOffsetTableOffset;
    public int colormapGrayscaleOffsetRecordLength;

    // [ rpf color converter subsection ]

    // [ rpf image description subheader ]
    public int numOfSpectralGroups;
    public int numOfSubframeTables;
    public int numOfSpectralBandTables;
    public int numOfSpectralBandLinesPerImageRow;
    public int numOfSubframesInEastWestDirection;
    public int numOfSubframesInNorthSouthDirection;
    public long numOfOutputColumnsPerSubframe;
    public long numOfOutputRowsPerSubframe;
    public long subframeMaskTableOffset;
    public long transparencyMaskTableOffset;

    // [ rpf related images section ]
    public RelatedImagesSection relatedImagesSection = null;

    public RpfFrameFileComponents(java.nio.ByteBuffer buffer)
    {
        this.componentLocationTable = new RpfLocationSection(buffer);

        if (0 < this.componentLocationTable.getCoverageSectionSubheaderLength())
            this.parseRpfCoverageSection(buffer);

        if (0 < this.componentLocationTable.getColorGrayscaleSectionSubheaderLength())
            this.parseColorGrayscaleSection(buffer);

        if (0 < this.componentLocationTable.getColormapSubsectionLength())
            this.parseColormapSubSection(buffer);

        if (0 < this.componentLocationTable.getColorConverterSubsectionLength())
            this.parseColorConverterSubsection(buffer);

        if (0 < this.componentLocationTable.getImageDescriptionSubheaderLength())
        {
            buffer.position(this.componentLocationTable.getImageDescriptionSubheaderLocation());
            this.parseImageDescriptionSubheader(buffer);
        }
        if (0 < this.componentLocationTable.getRelatedImagesSectionSubheaderLength())
        {
            buffer.position(this.componentLocationTable.getRelatedImagesSectionSubheaderLocation());
            this.relatedImagesSection = new RelatedImagesSection(buffer);
        }
    }

    private void parseImageDescriptionSubheader(java.nio.ByteBuffer buffer)
    {
        this.numOfSpectralGroups = NitfsUtil.getUShort(buffer);
        this.numOfSubframeTables = NitfsUtil.getUShort(buffer);
        this.numOfSpectralBandTables = NitfsUtil.getUShort(buffer);
        this.numOfSpectralBandLinesPerImageRow = NitfsUtil.getUShort(buffer);
        this.numOfSubframesInEastWestDirection = NitfsUtil.getUShort(buffer);
        this.numOfSubframesInNorthSouthDirection = NitfsUtil.getUShort(buffer);
        this.numOfOutputColumnsPerSubframe = NitfsUtil.getUInt(buffer);
        this.numOfOutputRowsPerSubframe = NitfsUtil.getUInt(buffer);
        this.subframeMaskTableOffset = NitfsUtil.getUInt(buffer);
        this.transparencyMaskTableOffset = NitfsUtil.getUInt(buffer);
    }

    private void parseColorConverterSubsection(java.nio.ByteBuffer buffer)
    {
        buffer.position(this.componentLocationTable.getColorConverterSubsectionLocation());
//        if (0 < this.numOfColorConverterOffsetRecords)
//            throw new NitfsRuntimeException("NitfsReader.NotImplemented.ColorConvertorSubsectionReader");
    }

    private void parseColormapSubSection(java.nio.ByteBuffer buffer)
    {
        buffer.position(this.componentLocationTable.getColormapSubsectionLocation());

        this.colormapOffsetTableOffset = NitfsUtil.getUInt(buffer);
        this.colormapGrayscaleOffsetRecordLength = NitfsUtil.getUShort(buffer);
        // read color / grayscale AND histogram records; builds a ColorMap (LUT)
        if (0 < this.numOfColorGrayscaleOffsetRecords)
        {
            rpfColorMaps = new RpfColorMap[this.numOfColorGrayscaleOffsetRecords];
            for (int i = 0; i < this.numOfColorGrayscaleOffsetRecords; i++)
            {
                rpfColorMaps[i] = new RpfColorMap(buffer, this.componentLocationTable.getColormapSubsectionLocation());
            }
        }
        else
            throw new NitfsRuntimeException("NitfsReader.InvalidNumberOfRpfColorGrayscaleRecords");
    }

    private void parseColorGrayscaleSection(java.nio.ByteBuffer buffer)
    {
        buffer.position(this.componentLocationTable.getColorGrayscaleSectionSubheaderLocation());

        this.numOfColorGrayscaleOffsetRecords = NitfsUtil.getByteAsShort(buffer);
        this.numOfColorConverterOffsetRecords = NitfsUtil.getByteAsShort(buffer);
        this.externalColorGrayscaleFilename = NitfsUtil.getString(buffer, 12);
    }

    private void parseRpfCoverageSection(java.nio.ByteBuffer buffer)
    {
        buffer.position(this.componentLocationTable.getCoverageSectionSubheaderLocation());

        this.nwUpperLeft = LatLon.fromDegrees(buffer.getDouble(), buffer.getDouble());
        this.swLowerleft = LatLon.fromDegrees(buffer.getDouble(), buffer.getDouble());
        this.neUpperRight = LatLon.fromDegrees(buffer.getDouble(), buffer.getDouble());
        this.seLowerRight = LatLon.fromDegrees(buffer.getDouble(), buffer.getDouble());

        this.verticalResolutionNorthSouth = buffer.getDouble();
        this.horizontalResolutionEastWest = buffer.getDouble();
        this.verticalIntervalLatitude = buffer.getDouble();
        this.horizontalIntervalLongitude = buffer.getDouble();
    }

    public class RelatedImagesSection
    {
        // [ rpf related images section subheader ]
        public long relatedImageDescriptionTableOffset;
        public int numOfRelatedImageDescriptionRecords;
        public int relatedImageDescriptionRecordLength;

        public RelatedImagesSection(java.nio.ByteBuffer buffer)
        {
            this.relatedImageDescriptionTableOffset = NitfsUtil.getUInt(buffer);
            this.numOfRelatedImageDescriptionRecords = NitfsUtil.getUShort(buffer);
            this.relatedImageDescriptionRecordLength = NitfsUtil.getUShort(buffer);
        }
    }
}
