#include <fcntl.h>
#include <linux/types.h>
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#include <strings.h>
#include <newt.h>
#include <stdlib.h>
#include <unistd.h>

#include "devices.h"
#include "install.h"
#include "intl.h"
#include "log.h"
#include "newt.h"
#include "scsi.h"
#include "windows.h"

#define CD_IDE 1
#define CD_SCSI 2
#define CD_OTHER 3

static struct { char * modname, * devname; } transTable[] = {
	{ "cm206", "cm206cd" },
	{ "sonycd535", "cdu535" },
	{ NULL, NULL }
} ;


#ifdef __i386__
static int setupCDdevicePanel(int * type) {
    char * menuItems[3];
    int cdromType = 0, rc;

    menuItems[0] = "SCSI";
    menuItems[1] = _("Other CDROM");
    menuItems[2] = NULL;

    if (*type == CD_OTHER)
	cdromType = 1;

    rc = newtWinMenu(_("CDROM type"), _("What type of CDROM do you have?"),
		     30, 5, 5, 7, menuItems,
		     &cdromType, _("Ok"), _("Back"), NULL);

    if (rc == 2) return INST_CANCEL;

    if (cdromType == 0)
	*type = CD_SCSI;
    else
	*type = CD_OTHER;

    return 0;
}
#endif /* __i386__ */

int findAtapi(char ** cddev) {
    struct deviceInfo * ide;
    int i;

    if (ideGetDevices(&ide)) return INST_ERROR;

    i = 0;
    while (ide[i].deviceName) {
	if (ide[i].type == DEVICE_CDROM) {
	    *cddev = ide[i].deviceName;
	    return 0;
	}
	i++;
    }

    return INST_ERROR;
}

int setupCDdevice(char ** cddev, struct driversLoaded ** dl) {
    int type = 0, rc = 0;
    struct driversLoaded * d;
    int i;
    int done = 0;

    /* Let's see if any CDROM's are already available */
    if (!findAtapi(cddev)) {
	logMessage("using device %s", *cddev);
	done = 1;
    }

    if (!done) {
#if defined(__sparc__) || defined(__alpha__)
	    /* It must be SCSI -- we'll give an error later if this is wrong */
	    setupSCSIInterfaces(1, dl, 0, 1);
	    *cddev = "scd0";
	    done =1;
#else
	    if (!findSCSIcdrom(cddev)) {
		done = 1;
	    } else if (kickstart) {
		setupSCSIInterfaces(1, dl, 0, 1);
		if (!findSCSIcdrom(cddev)) done = 1;
	    }
#endif
    }

#ifdef __i386__
	while (rc || !done) {
	    rc = setupCDdevicePanel(&type);
	    if (rc) return rc;

	    switch (type) {
	      case CD_SCSI:
		rc = setupSCSIInterfaces(0, dl, 0, 1);
		if (rc == INST_ERROR) return rc;
		*cddev = "scd0";
		done = 1;
		break;

	      case CD_OTHER:
		rc = loadDeviceDriver(DRIVER_CDROM, dl, 0);
		if (!rc) {
		    d = *dl;
		    *cddev = "bad_device";
		    while (d) {
			if (d->type == DRIVER_CDROM) {
			    *cddev = d->module;
			    break;
			}
			d = d->next;
		    }

		    for (i = 0; transTable[i].modname; i++) {
			if (!strcmp(*cddev, transTable[i].modname)) {
			    *cddev = transTable[i].devname;
			    break;
			}
		    }
		    done = 1;
		}
		break;
	    }
	} 
#endif /* __i386__ */

    winStatus(35, 3, "CDROM", _("Initializing CDROM..."));
    sleep(2);
    newtPopWindow();

    return 0;
}

int removeCDmodule(struct driversLoaded ** dl) {
    /* this wil fail silently if no CD module has been loaded */
    removeDeviceDriver(DRIVER_CDROM, dl);

    return 0;
}

int findSCSIcdrom(char ** cddev) {
    struct deviceInfo * scsi;
    int i;

    if (!scsiDeviceAvailable()) return INST_ERROR;

    if (scsiGetDevices(&scsi)) return INST_ERROR;

    i = 0;
    while (scsi[i].deviceName) {
	if (scsi[i].type == DEVICE_CDROM) {
	    *cddev = scsi[i].deviceName;
	    return 0;
	}
	i++;
    }

    return INST_ERROR;
}