//  
//   Rebex Sample Code License
// 
//   Copyright 2025, REBEX CR s.r.o.
//   All rights reserved.
//   https://www.rebex.net/
// 
//   Permission to use, copy, modify, and/or distribute this software for any
//   purpose with or without fee is hereby granted.
// 
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
// 

using System;
using System.IO;

using Rebex.IO;
using Rebex.IO.Compression;

namespace Rebex.Samples
{
    /// <summary>
    /// Command line utility that displays information about a ZIP archive:
    /// number of files, file names, compressed/uncompressed lengths and last modification dates.
    /// </summary>
    class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        /// <param name="args">Program arguments.</param>
        static void Main(string[] args)
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            // display the header
            string applicationName = AppDomain.CurrentDomain.FriendlyName;
            Console.WriteLine("==============================================================");
            Console.WriteLine(" Rebex {0} - displays information about a ZIP archive", applicationName);
            Console.WriteLine("==============================================================");

            // check whether a path to a ZIP archive was specified
            if (args.Length != 1)
            {
                // if not, display help and exit
                Console.WriteLine("Syntax: {0} zip-file-path", applicationName);
                Console.WriteLine(@"Example: {0} C:\archive.zip", applicationName);
                return;
            }

            // get ZIP archive path
            string zipArchivePath = args[0];

            try
            {
                // open the ZIP archive (in read-only mode)
                using (ZipArchive zip = new ZipArchive(zipArchivePath, ArchiveOpenMode.Open, ArchiveAccessMode.Read))
                {
                    // retrieve all files in the archive => use recursive GetItems
                    ZipItemCollection files = zip.GetItems("*", TraversalMode.Recursive, ArchiveItemTypes.Files);

                    if (files.Count == 0)
                    {
                        Console.WriteLine("There are no files within the archive.");
                    }
                    else
                    {
                        // sort the files by path (directories first)
                        files.Sort();

                        // total uncompressed length of the all files within the archive
                        long totalFilesLength = 0;

                        // display information about each file
                        Console.WriteLine("Last modified       Uncomp.len   Comp.len  Ratio  Path");
                        Console.WriteLine("--------------------------------------------------------------");
                        foreach (ZipItem file in files)
                        {
                            // update total uncompressed length
                            totalFilesLength += file.Length;

                            // compute compress ratio
                            double compressRatio = 0;
                            if (file.Length > 0)
                                compressRatio = (1 - (double)file.CompressedLength / (double)file.Length) * 100;

                            string lastWriteTime = string.Empty;
                            if (file.LastWriteTime.HasValue)
                                lastWriteTime = file.LastWriteTime.Value.ToString("u").TrimEnd('Z');

                            // display item info
                            Console.WriteLine("{0,19} {1,10} {2,10} {3,6:F2}% {4}",
                                lastWriteTime, file.Length, file.CompressedLength, compressRatio, file.Path);
                        }
                        Console.WriteLine("--------------------------------------------------------------");

                        // display count of files
                        Console.WriteLine("Total number of files: {0}", files.Count);

                        // read length of the ZIP archive
                        long archiveLength = new FileInfo(zipArchivePath).Length;

                        // displays some more info
                        Console.WriteLine("Total archive length (compressed): {0}", archiveLength);
                        Console.WriteLine("Total length of uncompressed files: {0}", totalFilesLength);

                        if (totalFilesLength > 0)
                        {
                            // compute compress ratio of the whole archive
                            double compressRatio = (1 - (double)archiveLength / (double)totalFilesLength) * 100;
                            Console.WriteLine("Archive compress ratio: {0:F2}%", compressRatio);
                        }
                    }

                    // display ZIP archive comment if it is not empty
                    if (zip.Comment != string.Empty)
                        Console.WriteLine("Archive comment: {0}", zip.Comment);
                }
            }
            catch (ZipException e)
            {
                // display an error reported by the ZIP component
                Console.WriteLine(e.Message);
            }
            catch (DirectoryNotFoundException e)
            {
                // display directory-not-found error
                Console.WriteLine(e.Message);
            }
            catch (FileNotFoundException e)
            {
                // display file-not-found error
                Console.WriteLine(e.Message);
            }
            catch (Exception e)
            {
                // display all other errors
                Console.WriteLine("Error occured: {0}", e);
            }
        }
    }
}
