/*
 * UPIWIN - Micro Pi Windowing Framework Kernel
 * Copyright (C) 2019 Amy Bowersox/Erbosoft Metaverse Design Solutions
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *-------------------------------------------------------------------------
 */
#include <zip.h>
#include "wintype.h"
#include "scode.h"
#include "config.h"
#include "log.h"
#include "resources.h"

/* conversion table from zip error codes to our HRESULT values */
static const struct tagCONVERSIONTABLE {
  int zip_err_code;
  HRESULT sys_err_code;
} conversion_table[] = {
  { ZIP_ER_OK,       S_OK },
  { ZIP_ER_SEEK,     STG_E_SEEKERROR },
  { ZIP_ER_READ,     STG_E_READFAULT },
  { ZIP_ER_WRITE,    STG_E_WRITEFAULT },
  { ZIP_ER_NOENT,    STG_E_FILENOTFOUND },
  { ZIP_ER_MEMORY,   E_OUTOFMEMORY },
  { ZIP_ER_INVAL,    E_INVALIDARG },
  { ZIP_ER_INTERNAL, E_UNEXPECTED },
  { -1, 0 }
}

/* references to system resource data in zip format */
extern uint8_t _binary_sysresources_zip_start[];
extern uint8_t _binary_sysresources_zip_end;
extern uint8_t _binary_sysresources_zip_size;

static zip_t *sysresource = NULL;   /* system resource file */

static HRESULT ziperror_to_hresult(zip_error_t *errinfo)
{
  register int i;

  for (i = 0; conversion_table[i].zip_err_code >= 0; i++)
    if (conversion_table[i].zip_err_code == errinfo->zip_err)
      return conversion_table[i].sys_err_code;
  return MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, errinfo->zip_err);
}

static void rsrc_cleanup(void)
{
  zip_close(sysresource);
  sysresource = NULL;
}

HRESULT Rsrc_setup(void)
{
  HRESULT hr = S_OK;
  zip_source_t *syssource;
  zip_error_t errinfo;

  Log(LDEBUG, "system resource length = %u", (UINT)(&_binary_sysresources_zip_size));
  zip_error_init(&errinfo);
  syssource = zip_source_buffer_create(_binary_sysresources_zip_start, (zip_uint64_t)(&_binary_sysresources_zip_size),
                                       0, &errinfo);
  if (!syssource)
  {
    hr = ziperror_to_hresult(&errinfo);
    goto error_0;
  }

  sysresource = zip_open_from_source(syssource, ZIP_RDONLY, &errinfo);
  if (!sysresource)
  {
    hr = ziperror_to_hresult(&errinfo);
    goto error_1;
  }

  hr = Config_exitfunc(rsrc_cleanup);
  if (FAILED(hr))
    rsrc_cleanup();
  return hr;

error_1:
  zip_source_free(syssource);
error_0:
  zip_error_fini(&errinfo);
  return hr;
}
