/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */
/*
 *
 * routines to sort an array of file objects
 * uses qsort alg
 *
 * Designed and implemented by Lou Montulli '94
 */

#include "mkutils.h"
#include "mkfsort.h"
#include "mkgeturl.h"

#ifdef PROFILE
#pragma profile on
#endif

PRIVATE int net_file_sort_method = SORT_BY_NAME;

/* print a text string in place of the NET_FileEntryInfo special_type int */
PUBLIC char *
NET_PrintFileType(int special_type)
{
	switch(special_type)
	  {
		case NET_FILE_TYPE:
			return("FILE");
		case NET_DIRECTORY:
			return("DIRECTORY");
		case NET_SYM_LINK:
			return("SYMBOLIC-LINK");
		case NET_SYM_LINK_TO_DIR:
			return("SYM-DIRECTORY");
		case NET_SYM_LINK_TO_FILE:
			return("SYM-FILE");
		default:
			PR_ASSERT(0);
			return("FILE");
	  }
}

PRIVATE void 
NET_SetFileSortMethod(int method)
{
	net_file_sort_method = method;
}

MODULE_PRIVATE void NET_FreeEntryInfoStruct(NET_FileEntryInfo *entry_info)
{
    if(entry_info) 
      {
        FREEIF(entry_info->filename);
        /* free the struct */
        PR_Free(entry_info);
      }
}

MODULE_PRIVATE NET_FileEntryInfo * NET_CreateFileEntryInfoStruct (void)
{
    NET_FileEntryInfo * new_entry = PR_NEW(NET_FileEntryInfo);

    if(!new_entry) 
       return(NULL);

	memset(new_entry, 0, sizeof(NET_FileEntryInfo));

	new_entry->permissions = -1;

	return(new_entry);

}

/* This function is used as a comparer function for the Qsort routine.
 * It uses a function FE_FileSortMethod() to determine the
 * field to sort on.
 *
 */
PRIVATE int
NET_CompareFileEntryInfoStructs (const void *ent2, const void *ent1, void *unused)
{
    int status;
    const NET_FileEntryInfo *entry1 = *(NET_FileEntryInfo **) ent1;
    const NET_FileEntryInfo *entry2 = *(NET_FileEntryInfo **) ent2;

	if(!entry1 || !entry2)
		return(-1);

    switch(net_file_sort_method)
      {
        case SORT_BY_SIZE:
                        /* both equal or both 0 */
                        if(entry1->size == entry2->size)
                            return(PL_strcmp(entry2->filename, entry1->filename));
                        else
                            if(entry1->size > entry2->size)
                                return(-1);
                            else
                                return(1);
                        /* break; NOT NEEDED */
        case SORT_BY_TYPE:
                        if(entry1->cinfo && entry1->cinfo->desc && 
										entry2->cinfo && entry2->cinfo->desc) 
                          {
                            status = PL_strcmp(entry1->cinfo->desc, entry2->cinfo->desc);
                            if(status)
                                return(status);
                            /* else fall to filename comparison */
                          }
                        return (PL_strcmp(entry2->filename, entry1->filename));
                        /* break; NOT NEEDED */
        case SORT_BY_DATE:
                        if(entry1->date == entry2->date) 
                            return(PL_strcmp(entry2->filename, entry1->filename));
                        else
                            if(entry1->size > entry2->size)
                                return(-1);
                            else
                                return(1);
                        /* break; NOT NEEDED */
        case SORT_BY_NAME:
        default:
                        return (PL_strcmp(entry2->filename, entry1->filename));
      }
}

/* sort the files
 */
MODULE_PRIVATE void
NET_DoFileSort(SortStruct * sort_list)
{
    NET_DoSort(sort_list, NET_CompareFileEntryInfoStructs);
}

#define PD_PUTS(s)  \
do { \
if(status > -1) \
	status = (*stream->put_block)(stream, s, PL_strlen(s)); \
} while(0)

PUBLIC int
NET_PrintDirectory(SortStruct **sort_base, NET_StreamClass * stream, char * path, URL_Struct *URL_s)
{
    NET_FileEntryInfo * file_entry;
    char out_buf[3096];
	char *esc_path = NET_Escape(path, URL_PATH);
    int i;
	int status=0;

    NET_DoFileSort(*sort_base);

	/* emit 300: URL CRLF */
	PL_strcpy(out_buf, "300: ");
    PD_PUTS(out_buf);
    PR_snprintf(out_buf, sizeof(out_buf), URL_s->address);
    PD_PUTS(out_buf);

	PL_strcpy(out_buf, CRLF);
    PD_PUTS(out_buf);

	/* emit 200: Filename Size Content-Type File-type Last-Modified */
	PL_strcpy(out_buf, "200: Filename Content-Length Content-Type File-type Last-Modified"CRLF);
    PD_PUTS(out_buf);

    for(i=0; status > -1 && (file_entry = (NET_FileEntryInfo *) 
                                NET_SortRetrieveNumber(*sort_base, i)) != 0;
			 i++)
      {


		char * esc_time = NET_Escape(ctime(&file_entry->date), URL_XALPHAS);

		strtok(file_entry->filename, "/");
        PR_snprintf(out_buf, sizeof(out_buf), "201: %s %ld %s %s %s"CRLF, 
                    file_entry->filename, 
                    file_entry->size,
                    file_entry->special_type == NET_DIRECTORY ? "application/http-index-format" :
                        file_entry->cinfo ? file_entry->cinfo->type : TEXT_PLAIN,
                    file_entry->special_type == NET_DIRECTORY ? "Directory" : "File",
                    esc_time);

		PR_Free(esc_time);
        
        PD_PUTS(out_buf);

        NET_FreeEntryInfoStruct(file_entry);
      }

    NET_SortFree(*sort_base);
    *sort_base = 0;

	PR_FREEIF(esc_path);
    if(status < 0)
        return(status);
	return(MK_DATA_LOADED);
}

#ifdef PROFILE
#pragma profile off
#endif

