/**
 *  Copyright © 2026, Luis Andrés Lange <https://javacomm.net>
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *  ----------------------------------------------------------------------------
 *
 *  Exhibit B - "Incompatible With Secondary Licenses" Notice
 *
 *  This Source Code Form is "Incompatible With Secondary Licenses",
 *  as defined by the Mozilla Public License, v. 2.0.
 *
 */
package net.javacomm.client.base;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;
import javax.swing.SwingWorker;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.javacomm.client.environment.Environment;
import net.javacomm.client.environment.GUI;



/**
 * Performs a version update for JavaComm with progress reporting.
 */
public class AutoupdateWorker extends SwingWorker<String, Integer> {

  private final static Logger log = LogManager.getLogger(AutoupdateWorker.class);
  private String downloadUrl;
  private Path zipPortable;
  private Path destination;

  /**
   * Initializes the updater.
   * 
   * @param sourceURL
   *                    the file to be downloaded.
   * @param destination
   *                    the target location for the downloaded file.
   */
  public AutoupdateWorker(String sourceURL, Path destination) {
    downloadUrl = sourceURL;
    zipPortable = destination;
  }



  @Override
  protected String doInBackground() throws Exception {

    long filesize = readFilesizeWithoutCompression();

    try(Client client = ClientBuilder.newClient()) {
      WebTarget webtarget = client.target(downloadUrl);
      try(
        InputStream result = webtarget.request(MediaType.APPLICATION_OCTET_STREAM).get(InputStream.class);
        BufferedInputStream inbuffer = new BufferedInputStream(result);
        BufferedOutputStream outbuffer = new BufferedOutputStream(Files.newOutputStream(zipPortable))
      ) {

        final int UPLOAD_DOWNLAOD_BUFFERSIZE = 65535;
        byte[] buffer = new byte[UPLOAD_DOWNLAOD_BUFFERSIZE];
        int read = 0;
        long count = 0;
        long prozent;
        while ((read = inbuffer.read(buffer)) != -1) {
          if (isCancelled()) {
            try {
              Files.deleteIfExists(zipPortable);
            }
            catch (IOException zipException) {
              log.error(zipException.getMessage());
            }
            firePropertyChange("error", null, new InterruptedException("Download aborted by user"));
            throw new InterruptedException("Download aborted by user");
          }
          count += read;
          outbuffer.write(buffer, 0, read);
          prozent = 100 * count / filesize;
          setProgress((int) prozent);
        }
      }
    }

    destination = Paths.get(zipPortable.getParent().toAbsolutePath().toString(), GUI.updateDir).normalize();
    org.nexuswob.util.Util.unzip(zipPortable, destination);
    Files.delete(zipPortable);
    if (Environment.getInstance().isLinux()) {
      Path runme = Paths.get(destination.toAbsolutePath().toString(), "runme.sh");
      Set<PosixFilePermission> filePermission = PosixFilePermissions.fromString("rwxr-xr-x");
      Files.setPosixFilePermissions(runme, filePermission);
    }

    return destination.toAbsolutePath().toString();
  }



  /**
   * Returns the size of file.
   * 
   * @return the file size in bytes
   */
  protected long readFilesizeWithoutCompression() {
    try(
      Client client = ClientBuilder.newClient();
      Response response = client.target(downloadUrl).request(MediaType.TEXT_PLAIN).head();
    ) {
      String contentLength = response.getHeaderString("Content-Length");
      return contentLength != null ? Long.parseLong(contentLength) : -1;
    }
  }

}
