/*
 * Copyright (c) 2013, 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:
//     Denise Smith - 2.6 - initial implementation
package org.eclipse.persistence.oxm.record;

import java.math.BigDecimal;
import java.math.BigInteger;

import jakarta.json.stream.JsonGenerator;
import javax.xml.namespace.QName;

import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.oxm.ConversionManager;

public class JsonGeneratorRecord extends JsonRecord<JsonRecord.Level> {

    private JsonGenerator jsonGenerator;
    private String rootKeyName;

    public JsonGeneratorRecord(JsonGenerator generator, String rootKeyName){
        super();
        this.jsonGenerator = generator;
        this.rootKeyName = rootKeyName;
    }

    @Override
    protected void startRootObject(){
        super.startRootObject();
        position.setKeyName(rootKeyName);
        setComplex(position, true);
    }

    @Override
    protected void finishLevel(){
        if(!(position.isCollection && position.isEmptyCollection() && position.getKeyName() == null)){
            jsonGenerator.writeEnd();
        }
        super.finishLevel();
    }

    @Override
    protected void startRootLevelCollection(){
        if(rootKeyName != null){
            jsonGenerator.writeStartArray(rootKeyName);
         }else{
             jsonGenerator.writeStartArray();
         }
    }

    @Override
    public void endCollection() {
        finishLevel();
    }

    @Override
    protected void setComplex(Level level, boolean complex){
        boolean isAlreadyComplex = level.isComplex;
        super.setComplex(level, complex);
        if(complex && !isAlreadyComplex){
            Level parentLevel = level.parentLevel;
            if(parentLevel != null && parentLevel.isCollection && parentLevel.isEmptyCollection()){
                parentLevel.setEmptyCollection(false);
            }
            if((parentLevel != null && parentLevel.isCollection && !parentLevel.isEmptyCollection()) || level.keyName == null){
                jsonGenerator.writeStartObject();
            }else{
                jsonGenerator.writeStartObject(level.keyName);
            }
        }
    }

    @Override
    protected void startEmptyCollection(){
        if (position.parentLevel != null && position.parentLevel.getSkipCount() > 0) {
            jsonGenerator.writeStartArray();
        } else {
            jsonGenerator.writeStartArray(position.keyName);
        }
    }

    @Override
    protected void writeEmptyCollection(Level level, String keyName){
        jsonGenerator.writeStartArray(keyName);
        jsonGenerator.writeEnd();
    }

    @Override
    protected void addValueToObject(Level level, String keyName, Object value, QName schemaType){

        if(value == NULL){
            jsonGenerator.writeNull(keyName);
        }else if(value instanceof Integer){
            jsonGenerator.write(keyName, (Integer)value);
        }else if(value instanceof BigDecimal){
            jsonGenerator.write(keyName, (BigDecimal)value);
        }else if(value instanceof BigInteger){
            jsonGenerator.write(keyName, (BigInteger)value);
        }else if(value instanceof Boolean){
            jsonGenerator.write(keyName, (Boolean)value);
        }else if(value instanceof Character){
            jsonGenerator.write(keyName, (Character)value);
        }else if(value instanceof Double){
            jsonGenerator.write(keyName, (Double)value);
        }else if(value instanceof Float){
            jsonGenerator.write(keyName, (Float)value);
        }else if(value instanceof Long){
            jsonGenerator.write(keyName, (Long)value);
        }else if(value instanceof String){
            jsonGenerator.write(keyName, (String)value);
        }else{
            ConversionManager conversionManager = getConversionManager();
            String convertedValue = conversionManager.convertObject(value, CoreClassConstants.STRING, schemaType);
            Class<Object> theClass = conversionManager.javaType(schemaType);
            if((schemaType == null || theClass == null) && (CoreClassConstants.NUMBER.isAssignableFrom(value.getClass()))){
                //if it's still a number and falls through the cracks we dont want "" around the value
                    BigDecimal convertedNumberValue = ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.BIGDECIMAL, schemaType);
                    jsonGenerator.write(keyName, convertedNumberValue);
            }else{
                jsonGenerator.write(keyName, convertedValue);
            }

        }
    }

    @Override
    protected void addValueToArray(Level level, Object value, QName schemaType){
        if(value == NULL){
            jsonGenerator.writeNull();
        }else if(value instanceof Integer){
            jsonGenerator.write((Integer)value);
        }else if(value instanceof BigDecimal){
            jsonGenerator.write((BigDecimal)value);
        }else if(value instanceof BigInteger){
            jsonGenerator.write((BigInteger)value);
        }else if(value instanceof Boolean){
            jsonGenerator.write((Boolean)value);
        }else if(value instanceof Character){
            jsonGenerator.write((Character)value);
        }else if(value instanceof Double){
            jsonGenerator.write((Double)value);
        }else if(value instanceof Float){
            jsonGenerator.write((Float)value);
        }else if(value instanceof Long){
            jsonGenerator.write((Long)value);
        }else if(value instanceof String){
            jsonGenerator.write((String)value);
        }else{
            ConversionManager conversionManager = getConversionManager();
            String convertedValue = conversionManager.convertObject(value, CoreClassConstants.STRING, schemaType);
            Class<Object> theClass = conversionManager.javaType(schemaType);
            if((schemaType == null || theClass == null) && (CoreClassConstants.NUMBER.isAssignableFrom(value.getClass()))){
                //if it's still a number and falls through the cracks we dont want "" around the value
                    BigDecimal convertedNumberValue = ((ConversionManager) session.getDatasourcePlatform().getConversionManager()).convertObject(value, CoreClassConstants.BIGDECIMAL, schemaType);
                    jsonGenerator.write(convertedNumberValue);

            }else{
                jsonGenerator.write(convertedValue);
            }
        }
    }
}
