#include "disk.h"


int
disk_create(disk_t* disk, char* name, int size, int flags) {
  if ((disk->file = fopen(name, "w+b")) == NULL)
    return -1;
  
  disk->layout.size = size;
  disk->layout.flags = flags;

  /* write the disk layout to the "disk" */
  if (fwrite(&disk->layout, 1, sizeof(disk_layout_t), disk->file)
      != sizeof(disk_layout_t)) {
    fclose(disk->file);
    return -1;
  }

  return 0;
}

int
disk_startup(disk_t* disk, char* name) {
  if ((disk->file = fopen(name, "r+b")) == NULL)
    return -1;
  
  if (fread(&disk->layout, 1, sizeof(disk_layout_t), disk->file) != 
      sizeof(disk_layout_t)) {
    fclose(disk->file);
    return -1;
  }

  return 0;
}

static void
disk_write_layout(disk_t* disk) {
  if (fseek(disk->file, 0, SEEK_SET) != 0)
    fclose(disk->file);
  else if (fwrite(&disk->layout, 1, sizeof(disk_layout_t), disk->file) != 
      sizeof(disk_layout_t))
    fclose(disk->file);
  else
    fflush(disk->file);
}

int
disk_shutdown(disk_t* disk) {
  
  fclose(disk->file);
  return 0;
}

void
disk_set_flags(disk_t* disk, int flags) {
  disk->layout.flags |= flags;
  disk_write_layout(disk);
}

void
disk_unset_flags(disk_t* disk, int flags) {
  disk->layout.flags ^= disk->layout.flags | flags;
  disk_write_layout(disk);
}

int
disk_read_block(disk_t* disk, int blocknum, char* buffer) {
  int offset = DISK_BLOCK_SIZE*(blocknum + 1);

  if (blocknum >= disk->layout.size)
    return -1;

  if (fseek(disk->file, offset, SEEK_SET) != 0) 
    return -1;
  else if (fread(buffer, 1, DISK_BLOCK_SIZE, disk->file) < DISK_BLOCK_SIZE)
    return -1;

  return 0;
}

int
disk_write_block(disk_t* disk, int blocknum, char* buffer) {
  int offset = DISK_BLOCK_SIZE*(blocknum + 1);

  if (blocknum >= disk->layout.size)
    return -1;
  else if (disk->layout.flags & DISK_READONLY)
    return -1;

  if (fseek(disk->file, offset, SEEK_SET) != 0) 
    return -1;
  else if (fwrite(buffer, 1, DISK_BLOCK_SIZE, disk->file) < DISK_BLOCK_SIZE)
    return -1;

  return 0;
}
