// vil_nitf2: Written by Rob Radtke (rob@) and Harry Voorhees (hlv@) of
// Stellar Science Ltd. Co. (stellarscience.com) for
// Air Force Research Laboratory, 2005.

#ifndef VIL_NITF2_CLASSIFICATION_H
#define VIL_NITF2_CLASSIFICATION_H

#include <string>
#include <map>
#include <utility>
#include "vil_nitf2.h"

#ifdef _MSC_VER
#  include <vcl_msvc_warnings.h>
#endif

class vil_nitf2_field_definitions;

// A purely static class that generates classification field definitions.
// Use \sa get_field_definitions() to get a field definition that will
// parse either a nitf 2.1 or nitf 2.0 stream.  Note that the two are
// very different, so be sure to ask for the right one.  They don't even
// have the same field width. In NITF 2.1, the classification string is
// fixed at 205 characters.  In NITF 2.0, it can either be 167 or 207
// characters depending on whether the conditional field SDEVT is present
// or not. The field names also vary according to the type of header
// that contains them.
//
class vil_nitf2_classification
{
public:

  // NITF file version
  enum file_version
  {
    V_UNKNOWN, V_NITF_10, V_NITF_20, V_NITF_21,
    // If you weren't confused enough already, now we're telling you
    // that NSIF 1.0 is the same as NITF 2.1. It's true though.
    V_NSIF_10 = V_NITF_21
  };

  // Classification fields are used in a number of places with slightly
  // different tag names and pretty names. In the file header the first
  // classification field is "FSCLAS" ("File Security Classification");
  // in the image subheader, the corresponding field is "ISCLAS"
  // ("Image Security Classification"). Fortunately, these differences
  // are consistent, so all tag names in one context can be generated by
  // prepending the same string to the base tag name; similarly for
  // the fields' pretty names. The tag_prefix and pretty_name_prefix
  // argument below allow the caller to generate the field definitions
  // appropriate to the context, e.g., "F" and "File", respectively,
  // in the case of a file header.
  static const vil_nitf2_field_definitions* get_field_definitions(
    const file_version& version,
    std::string tag_prefix, std::string pretty_name_prefix );

  // Like get_field_defintions(), but appends fields to defs instead
  // of returning them.
  static void add_field_defs(
    vil_nitf2_field_definitions* defs, const file_version& version,
    std::string prefix, const std::string& pretty_name_prefix);

private:
  // Purely static class; don't instantiate.
  vil_nitf2_classification() = delete;

  // A cache of field definitions, indexed by version, tag_prefix and
  // pretty_name_prefix.
  typedef std::pair< file_version, std::pair< std::string, std::string> >
    type_field_defs_key;
  typedef std::map< type_field_defs_key, vil_nitf2_field_definitions*>
    type_field_defs_map;
  static type_field_defs_map & s_field_definitions();

  // so these static members can be cleaned up when the program is done
  // using nitf files
  friend class type_field_defs_map_t;
};

#endif //VIL_NITF2_CLASSIFICATION_H
