/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.oxm;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import jakarta.activation.DataHandler;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import jakarta.mail.internet.ContentType;
import jakarta.mail.internet.MimeMultipart;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;

public class XMLBinaryDataHelper {
    protected static XMLBinaryDataHelper binaryDataHelper;
    public Class DATA_HANDLER;
    public Class IMAGE;
    public Class SOURCE;
    public Class MULTIPART;

    public XMLBinaryDataHelper() {
        if (DATA_HANDLER == null) {
            initializeDataTypes();
        }
    }

    public static XMLBinaryDataHelper getXMLBinaryDataHelper() {
        if (binaryDataHelper == null) {
            setXMLBinaryDataHelper(new XMLBinaryDataHelper());
        }
        return binaryDataHelper;
    }

    public static void setXMLBinaryDataHelper(XMLBinaryDataHelper helper) {
        binaryDataHelper = helper;
    }

    public void initializeDataTypes() {
        //initialize types in this method to avoid loading them when the class is loaded
        DATA_HANDLER = jakarta.activation.DataHandler.class;
        IMAGE = java.awt.Image.class;
        SOURCE = javax.xml.transform.Source.class;
        MULTIPART = jakarta.mail.internet.MimeMultipart.class;
    }

    public Object convertObject(Object obj, Class classification, CoreAbstractSession session, CoreContainerPolicy cp) {
        if( obj instanceof List && cp != null){
            List theList = (List)obj;
            Object container = cp.containerInstance(theList.size());
            for(int i=0; i<theList.size(); i++){
                Object next = theList.get(i);
                cp.addInto(convertSingleObject(next, classification, session), container, session);
            }
            return container;
        }
        return convertSingleObject(obj, classification, session);

    }
    public Object convertSingleObject(Object obj, Class classification, CoreAbstractSession session) {
        if (classification == DATA_HANDLER) {
            return convertObjectToDataHandler(obj, session);
        } else if (classification == IMAGE) {
            return convertObjectToImage(obj);
        } else if (classification == SOURCE) {
            return convertObjectToSource(obj);
        } else if (classification == MULTIPART) {
            return convertObjectToMultipart(obj);
        } else {
            return session.getDatasourcePlatform().getConversionManager().convertObject(obj, classification);
        }
    }
    public EncodedData getBytesFromDataHandler(DataHandler handler) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            handler.writeTo(output);
        } catch (IOException ex) {
            throw ConversionException.couldNotBeConverted(handler, byte[].class, ex);
        }

        return new EncodedData(output.toByteArray(), handler.getContentType());
    }

    public List<byte[]> getBytesListForBinaryValues(List attributeValue, Marshaller marshaller, String mimeType){
        List returnList = new ArrayList(attributeValue.size());
        for(int i=0;i<attributeValue.size(); i++){
            Object next = attributeValue.get(i);
            EncodedData nextEncodedData = getBytesForSingleBinaryValue(next, marshaller, mimeType);
            returnList.add(nextEncodedData.getData());
        }
        return returnList;
    }

    public EncodedData getBytesForBinaryValue(Object attributeValue, Marshaller marshaller, String mimeType) {
        return getBytesForSingleBinaryValue(attributeValue, marshaller, mimeType);

    }

    public EncodedData getBytesForSingleBinaryValue(Object attributeValue, Marshaller marshaller, String mimeType) {

        if (attributeValue instanceof DataHandler) {
            return getBytesFromDataHandler((DataHandler) attributeValue);
        } else if (attributeValue instanceof Image) {
            return getBytesFromImage((Image) attributeValue, mimeType);
        } else if (attributeValue instanceof Source) {
            return getBytesFromSource((Source) attributeValue, marshaller, mimeType);
        } else if (attributeValue instanceof MimeMultipart) {
            return getBytesFromMultipart((MimeMultipart) attributeValue, marshaller);
        } else if (attributeValue.getClass() == CoreClassConstants.APBYTE) {
            return new EncodedData((byte[]) attributeValue, mimeType);
        } else if (attributeValue.getClass() == CoreClassConstants.ABYTE) {
            return getBytesFromByteObjectArray((Byte[]) attributeValue, mimeType);
        }

        return new EncodedData(new byte[0], null);
    }

    public EncodedData getBytesFromMultipart(MimeMultipart value, Marshaller marshaller) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            ContentType contentType = new ContentType(value.getContentType());
            String boundary = contentType.getParameter("boundary");

            output.write(Constants.cr().getBytes());
            output.write(("Content-Type: " + contentType.getBaseType() + "; boundary=\"" + boundary + "\"\n").getBytes());
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConverted(value, byte[].class, ex);
        }

        try {
            value.writeTo(output);
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConverted(value, byte[].class, ex);
        }
        return new EncodedData(output.toByteArray(), value.getContentType());
    }

    public EncodedData getBytesFromSource(Source source, Marshaller marshaller, String mimeType) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        StreamResult result = new StreamResult(out);
        marshaller.getTransformer().transform(source, result);
        if (mimeType == null) {
            mimeType = "application/xml";
        }
        return new EncodedData(out.toByteArray(), mimeType);
    }

    public EncodedData getBytesFromByteObjectArray(Byte[] bytes, String mimeType) {
        byte[] data = new byte[bytes.length];
        for (int i = 0; i < data.length; i++) {
            data[i] = bytes[i];
        }
        return new EncodedData(data, mimeType);
    }

    public EncodedData getBytesFromImage(Image image, String mimeType) {
        if ((mimeType == null) || mimeType.startsWith("image/*")) {
            mimeType = "image/png";
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            Iterator itr = ImageIO.getImageWritersByMIMEType(mimeType);
            if (itr.hasNext()) {
                ImageWriter w = (ImageWriter) itr.next();
                w.setOutput(ImageIO.createImageOutputStream(outputStream));
                w.write(convertToBufferedImage(image));
                w.dispose();
            } else {
                throw XMLMarshalException.noEncoderForMimeType(mimeType);
            }

            return new EncodedData(outputStream.toByteArray(), mimeType);
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConverted(image, byte[].class, ex);
        }
    }

    private BufferedImage convertToBufferedImage(Image image) throws IOException {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        } else {
            MediaTracker tracker = new MediaTracker(new Component() {
            });// not sure if this is the right thing to do.
            tracker.addImage(image, 0);
            try {
                tracker.waitForAll();
            } catch (InterruptedException e) {
                throw new IOException(e.getMessage());
            }
            BufferedImage bufImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);

            Graphics g = bufImage.createGraphics();
            g.drawImage(image, 0, 0, null);
            return bufImage;
        }
    }

    public Object convertObjectToMultipart(Object obj) {
        if (obj instanceof MimeMultipart) {
            return obj;
        }
        if (obj instanceof DataHandler) {
            try {
                if (((DataHandler) obj).getContent() instanceof MimeMultipart) {
                    MimeMultipart multipart = (MimeMultipart) ((DataHandler) obj).getContent();
                    return multipart;
                } else {
                    return new MimeMultipart(((DataHandler) obj).getDataSource());
                }
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, MULTIPART, ex);
            }
        } else if (obj instanceof byte[]) {
            try {
                byte[] bytes = (byte[]) obj;
                java.io.InputStreamReader in = new java.io.InputStreamReader(new ByteArrayInputStream(bytes));
                int i = 0;
                while (i != -1) {
                    i = in.read();
                }
                return new MimeMultipart(new ByteArrayDataSource((byte[]) obj, "multipart/mixed"));
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, MULTIPART, ex);
            }
        } else if (obj instanceof Byte[]) {
            Byte[] objectBytes = (Byte[]) obj;
            byte[] bytes = new byte[objectBytes.length];
            for (int i = 0; i < objectBytes.length; i++) {
                bytes[i] = objectBytes[i];
            }
            try {
                return new MimeMultipart(new ByteArrayDataSource(bytes, "multipart/mixed"));
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, MULTIPART, ex);
            }
        }
        return null;
    }

    public Object convertObjectToImage(Object obj) {
        if (obj instanceof Image) {
            return obj;
        }
        if (obj instanceof DataHandler) {
            try {
                if (((DataHandler) obj).getContent() instanceof Image) {
                    Image image = (Image) ((DataHandler) obj).getContent();
                    return image;
                } else {
                    return ImageIO.read(((DataHandler) obj).getInputStream());
                }
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, IMAGE, ex);
            }
        } else if (obj instanceof byte[]) {
            ByteArrayInputStream stream = new ByteArrayInputStream((byte[]) obj);
            try {
                return ImageIO.read(stream);
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, IMAGE, ex);
            }
        } else if (obj instanceof Byte[]) {
            Byte[] objectBytes = (Byte[]) obj;
            byte[] bytes = new byte[objectBytes.length];
            for (int i = 0; i < objectBytes.length; i++) {
                bytes[i] = objectBytes[i];
            }
            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
            try {
                return ImageIO.read(stream);
            } catch (Exception ex) {
                throw ConversionException.couldNotBeConverted(obj, IMAGE, ex);
            }
        }
        return null;
    }

    public String stringFromDataHandler(DataHandler source, QName schemaTypeQName, CoreAbstractSession session) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            source.writeTo(output);
            return (String) ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(output.toByteArray(), String.class, schemaTypeQName);
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConverted(source, CoreClassConstants.STRING, ex);
        }
    }

    public String stringFromDataHandler(Object source, QName schemaTypeQName, CoreAbstractSession session) {
        return stringFromDataHandler((DataHandler) source, schemaTypeQName, session);
    }

    public String stringFromImage(Image image, QName schemaTypeQName, CoreAbstractSession session) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            String mimeType = "image/png";
            Iterator itr = ImageIO.getImageWritersByMIMEType(mimeType);
            if (itr.hasNext()) {
                ImageWriter w = (ImageWriter) itr.next();
                w.setOutput(ImageIO.createImageOutputStream(outputStream));
                w.write(convertToBufferedImage(image));
                w.dispose();
            } else {
                throw XMLMarshalException.noEncoderForMimeType(mimeType);
            }

            return ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).buildBase64StringFromBytes(outputStream.toByteArray());
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConverted(image, byte[].class, ex);
        }
    }

    public String stringFromSource(Source source, QName schemaTypeQName, CoreAbstractSession session) {
        DataHandler handler = new DataHandler(source, "text/xml");
        return stringFromDataHandler(handler, schemaTypeQName, session);
    }

    public String stringFromMultipart(MimeMultipart multipart, QName schemaTypeQName, CoreAbstractSession session) {
        DataHandler handler = new DataHandler(multipart, multipart.getContentType());
        return stringFromDataHandler(handler, schemaTypeQName, session);
    }

    public DataHandler convertObjectToDataHandler(Object sourceObject, CoreAbstractSession session) {
        DataHandler handler = null;
        if (sourceObject instanceof DataHandler) {
            return (DataHandler) sourceObject;
        } else if (sourceObject instanceof byte[]) {
            byte[] bytes = (byte[]) sourceObject;
            handler = new DataHandler(new ByteArrayDataSource(bytes, "application/octet-stream"));

        } else if (sourceObject instanceof Byte[]) {
            byte[] bytes = (byte[]) session.getDatasourcePlatform().getConversionManager().convertObject(sourceObject, CoreClassConstants.APBYTE);
            handler = new DataHandler(new ByteArrayDataSource(bytes, "application/octet-stream"));
        }
        if (sourceObject instanceof String) {
            //assume base64 String
            byte[] bytes = ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertSchemaBase64ToByteArray(sourceObject);
            handler = new DataHandler(new ByteArrayDataSource(bytes, "application/octet-stream"));
        } else if (sourceObject instanceof Image) {
            handler = new DataHandler(sourceObject, "image/jpeg");
        } else if (sourceObject instanceof Source) {
            handler = new DataHandler(sourceObject, "text/xml");
        } else if (sourceObject instanceof MimeMultipart) {
            handler = new DataHandler(sourceObject, ((MimeMultipart) sourceObject).getContentType());
        }
        return handler;
    }

    public Object convertObjectToSource(Object obj) {
        if(obj == null) {
            return null;
        }
        if (obj instanceof Source) {
            return obj;
        }
        if(obj.getClass() == CoreClassConstants.STRING) {
            return new StreamSource(new StringReader((String)obj));
        }
        if (obj instanceof DataHandler) {
            try {
                InputStream object = ((DataHandler)obj).getInputStream();
                return new StreamSource(object);
            } catch (Exception ex) {
                try {
                    Object object = ((DataHandler)obj).getContent();
                    convertObjectToSource(object);
                } catch(Exception ioException) {
                    throw ConversionException.couldNotBeConverted(obj, Source.class);
                }
            }
        } else if (obj instanceof byte[]) {
            return new ByteArraySource((byte[])obj);
        } else if (obj instanceof Byte[]) {
            Byte[] objectBytes = (Byte[]) obj;
            byte[] bytes = new byte[objectBytes.length];
            for (int i = 0; i < objectBytes.length; i++) {
                bytes[i] = objectBytes[i];
            }
            return new ByteArraySource(bytes);
        } else if(obj instanceof InputStream) {
            return new StreamSource((InputStream)obj);
        }
        return null;
    }

    // Made static final for performance reasons.
    /**
     * INTERNAL
     * @author mmacivor
     *
     */
    public static final class EncodedData {
        private byte[] data;
        private String mimeType;

        public EncodedData(byte[] bytes, String contentType) {
            data = bytes;
            mimeType = contentType;
        }

        public String getMimeType() {
            return mimeType;
        }

        public byte[] getData() {
            return data;
        }

        public void setMimeType(String type) {
            mimeType = type;
        }

        public void setData(byte[] bytes) {
            data = bytes;
        }
    }
}
