/* Copyright 2008 David Moews (dmoews@fastmail.fm)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
#ifndef ISO9660_CHECK_INCL

#define ISO9660_CHECK_INCL

#include <iosfwd>

#include "Iso9660.h"

enum SortingType { Sort_Iso9660, Sort_Lex, Sort_None };

struct CheckingOptions
{
  bool do_volume_info;
  bool do_boot_records;
  bool do_volume_partitions;
  int do_volume_descriptor;   // Index, or -1 for all, or -2 to skip
  bool do_overlapping_hierarchies;  
         // Check for overlapping directory/path table/volume descriptor 
         // extents.

  bool do_overlapping_files;
         // Check for overlapping file/directory/path table/volume descriptor 
         // extents
         // (we allow one file to be part of
         // the hierarchy of >1 volume descriptor.)  NB: overlapping file
         // extents are not prohibited by the standard.

  bool do_overlapping_partitions;
         // Check for overlapping volume partition extents.
         // NB: overlapping volume partition extents are not prohibited 
         // by the standard.

  // Sorting types to use for PVD, SVD hierarchies
  SortingType primary_sorting_type;
  SortingType secondary_sorting_type;

  CheckingOptions() :
       do_volume_info(true),
       do_boot_records(true),
       do_volume_partitions(true),
       do_volume_descriptor(-1),
       do_overlapping_hierarchies(true),
       do_overlapping_files(true),
       do_overlapping_partitions(true),
       primary_sorting_type(Sort_Iso9660),
       secondary_sorting_type(Sort_Lex)
             { }
};

struct CheckingOutput
{
  // Fatal issues
  bool dot_coherency;
  bool almost_dot_coherency;
  bool dotdot_coherency;
  bool almost_dotdot_coherency;
  bool directory_coherency;
  bool directory_sorted;
  bool blocks_within_range;
  bool blocks_lowest_sector;
  bool xar_length_ok;
  bool xars_parse_ok;
  bool no_volume_seq_problem;
  bool no_multivolume_problem;
  bool no_overlapping_hierarchies;
  bool character_set_restrictions_ok;
  bool filename_restrictions_ok;
  bool descriptor_files_found_in_root;

  // Non-fatal issues

  bool is_not_multivolume;
  bool no_multisection_files;
  bool no_overlapping_partitions;
  bool no_overlapping_files;
  bool level_1_name_restrictions_ok;

  // Maxima.  For compliance, these should be <= (8, 255, ???, ???, 30, 31.)
  std::size_t max_level;
  std::size_t max_non_dir_pathname_length;
  std::size_t max_directory_pathname_length;
  std::size_t max_non_dir_identifier_length;
  std::size_t max_non_dir_name_plus_extension_length;
  std::size_t max_directory_identifier_length;

  // Other
  u32 num_partition_blocks;
  u32 num_hierarchy_blocks;
  u32 num_file_blocks;
  u32 num_volume_space_blocks;

  CheckingOutput() : 
        dot_coherency(true),
        almost_dot_coherency(true),
        dotdot_coherency(true),
        almost_dotdot_coherency(true),
        directory_coherency(true),
        directory_sorted(true),
        blocks_within_range(true),
        blocks_lowest_sector(true),
        xar_length_ok(true),
        xars_parse_ok(true),
        no_volume_seq_problem(true),
        no_multivolume_problem(true),
        no_overlapping_hierarchies(true),
        character_set_restrictions_ok(true),
        filename_restrictions_ok(true),
        descriptor_files_found_in_root(true),

        is_not_multivolume(true),
        no_multisection_files(true),
        no_overlapping_partitions(true),
        no_overlapping_files(true),
        level_1_name_restrictions_ok(true),

        max_level(0u),
        max_non_dir_pathname_length(0u),
        max_directory_pathname_length(0u),
        max_non_dir_identifier_length(0u),
        max_non_dir_name_plus_extension_length(0u),
        max_directory_identifier_length(0u),

        num_partition_blocks(0u),
        num_hierarchy_blocks(0u),
        num_file_blocks(0u),
        num_volume_space_blocks(0u)
          { }
};

//
// Verify ISO9660 compliance and other issues.
// Volume may be changed by parsing XARs, if present.
//
void check_volume(Volume &v, const CheckingOptions &opts, 
                  CheckingOutput *p_out);

// Print report based on options 
void print_options_report(std::ostream &o, const CheckingOptions &opts);

// Print report based on output
void print_output_report(std::ostream &o, const CheckingOutput &out);

#endif
