/*
       _             __
  ____(_)__ _______ / /____ ____
 / __/ (_-</ __(_-</ __/ -_) __/
/_/ /_/___/\__/___/\__/\__/_/

Napster client for RISC OS
Copyright (C) 2000 Robert Dimond

This file (sort.c) was kindly donated by Neil Walker.

Portions are based on gnap by Ryan Dahl.

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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA

Bransley Cottage, Cleobury Mortimer, Kidderminster, WORCS. DY14 0BZ
England. robdimond@cwcom.net

*/

#include <stdlib.h>
#include <string.h>

#include "sort.h"


search_result *search_resblock;
search_result *search_tail;


void sort_results(compare_fn compare) {
  search_result *wrt_first, *wrt_last;
  search_result *read=search_resblock, *best, *search, *rd_prev, *rd_next;

  wrt_first=(search_result *) NULL; //GCC wants an explicit cast, for some
  wrt_last=(search_result *) NULL;  //reason!?
  /* algorithm here is rather simplistic:
   * this is a selection sort, with two lists : one unsorted, one sorted.
   * The 'best' match is removed from the unsorted list,
   * and added to the tail of the sorted list.
   */
  while (read!=NULL) {
    best=read;
    search=read;
    while (search!=NULL) {
      if (compare(search,best) < 0)
        best=search;
      search=search->next;
    }
    /* the best of the unsorted entries is now pointed to by 'best' */
    /* remove it from the unsorted list */
    rd_prev = best->prev;
    rd_next = best->next;
    if (NULL!=rd_prev)
      rd_prev->next = rd_next;
    if (NULL!=rd_next)
      rd_next->prev = rd_prev;
    /* and add it to the tail of the sorted list */
    if (wrt_first==NULL)
      wrt_first=best;
    if (wrt_last!=NULL)
      wrt_last->next=best;
    best->prev=wrt_last;
    best->next=(search_result *) NULL;
    wrt_last=best;

    if (read==best)
      read=rd_next;
  }
  search_resblock = wrt_first;
  search_tail = wrt_last;
}

int compare_file(search_result *a, search_result *b) {
  return strcmp(a->filename,b->filename);
}

int compare_user(search_result *a, search_result *b) {
  return strcmp(a->user,b->user);
}

int compare_size(search_result *a, search_result *b) {
  return a->size - b->size;
}

int compare_bitrate(search_result *a, search_result *b) {
  return a->bitrate - b->bitrate;
}

int compare_freq(search_result *a, search_result *b) {
  return a->frequency - b->frequency;
}

int compare_speed(search_result *a, search_result *b) {
  return a->speed - b->speed;
}

int compare_length(search_result *a, search_result *b) {
  /* > I assume the number field corresponds to length... nsw */
  /* correct!  --rob */
  return a->number - b->number;
}

void add_res(search_result *res) {

  if(search_resblock==NULL)
  {
   search_resblock=res;
  }
  else
  {
   search_tail->next=res;
   res->prev=search_tail;
  }
  search_tail=res;
}




