/*
 * 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.record.deferred;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.internal.oxm.record.ExtendedContentHandler;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

/**
 * <p><b>Purpose</b>: ContentHandler to store events until we know if we are dealing with a simple, complex or empty element.
 * <p><b>Responsibilities</b>:<ul>
 * <li> Store events until will know if the element is simple, complex or empty
 * <li> Return control to the original unmarshalRecord
 * </ul>
 */
public abstract class DeferredContentHandler implements ExtendedContentHandler, LexicalHandler {
    private int levelIndex;
    private List<SAXEvent> events;
    private UnmarshalRecord parent;
    private boolean startOccurred;
    private boolean charactersOccurred;
    private boolean attributesOccurred;

    protected DeferredContentHandler(UnmarshalRecord parentRecord) {
        levelIndex = 0;
        events = new ArrayList<>();
        this.parent = parentRecord;
    }


    @Override
    public void setNil(boolean isNil) {}

    protected abstract void processEmptyElement() throws SAXException;

    protected abstract void processComplexElement() throws SAXException;

    protected abstract void processSimpleElement() throws SAXException;

    protected void processEmptyElementWithAttributes() throws SAXException {
        processEmptyElement();
    }

    protected void executeEvents(UnmarshalRecord unmarshalRecord) throws SAXException {
        for (int i = 0; i < events.size(); i++) {
            SAXEvent nextEvent = events.get(i);
            nextEvent.processEvent(unmarshalRecord);
        }
        XMLReader parentXMLReader = parent.getXMLReader();
        if (parentXMLReader.getContentHandler().equals(this)) {
            parentXMLReader.setContentHandler(unmarshalRecord);
            parentXMLReader.setLexicalHandler(unmarshalRecord);
        }
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        StartPrefixMappingEvent event = new StartPrefixMappingEvent(prefix, uri);
        events.add(event);
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {
        EndPrefixMappingEvent event = new EndPrefixMappingEvent(prefix);
        events.add(event);
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        levelIndex++;

        //Copy attributes because some parsers reuse the Attributes object across start element events
        Attributes copiedAttrs = buildAttributeList(atts);

        StartElementEvent event = new StartElementEvent(uri, localName, qName, copiedAttrs);
        events.add(event);

        if (startOccurred) {
            //we know it's complex and non-null
            processComplexElement();
            return;
        }

        startOccurred = true;
    }

    protected Attributes buildAttributeList(Attributes attrs) throws SAXException {
        int attrsLength = attrs.getLength();
        AttributeList attributes = new AttributeList(attrsLength);
        for (int i = 0; i < attrsLength; i++) {
            String qName = attrs.getQName(i);
            String uri = attrs.getURI(i);
            attributes.addAttribute(attrs.getLocalName(i), qName, uri, attrs.getType(i), attrs.getValue(i), i);
            if(!javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(uri) && (null != qName && !qName.startsWith(javax.xml.XMLConstants.XMLNS_ATTRIBUTE))) {
                attributesOccurred = true;
            }
        }
        return attributes;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        levelIndex--;
        EndElementEvent event = new EndElementEvent(uri, localName, qName);
        events.add(event);

        if (charactersOccurred) {
            //we know it is a simple element
            processSimpleElement();
        } else if(startOccurred){
            //we know it is an empty element
            if(attributesOccurred) {
                processEmptyElementWithAttributes();
            } else {
                processEmptyElement();
            }
        }

        if ((levelIndex == 0) && (parent != null)) {
            XMLReader xmlReader = parent.getXMLReader();
            xmlReader.setContentHandler(parent);
            xmlReader.setLexicalHandler(parent);
        }
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        DocumentLocatorEvent event = new DocumentLocatorEvent(locator);
        events.add(event);
    }

    @Override
    public void startDocument() throws SAXException {
        StartDocumentEvent event = new StartDocumentEvent();
        events.add(event);
    }

    @Override
    public void endDocument() throws SAXException {
        EndDocumentEvent event = new EndDocumentEvent();
        events.add(event);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        charactersOccurred = true;
        CharactersEvent event = new CharactersEvent(ch, start, length);
        events.add(event);
    }

    @Override
    public void characters(CharSequence characters) {
        charactersOccurred = true;
        CharactersEvent event = new CharactersEvent(characters);
        events.add(event);
    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
        IgnorableWhitespaceEvent event = new IgnorableWhitespaceEvent(ch, start, length);
        events.add(event);
    }

    @Override
    public void processingInstruction(String target, String data) throws SAXException {
        ProcessingInstructionEvent event = new ProcessingInstructionEvent(target, data);
        events.add(event);
    }

    @Override
    public void skippedEntity(String name) throws SAXException {
        SkippedEntityEvent event = new SkippedEntityEvent(name);
        events.add(event);
    }

    @Override
    public void startDTD(String name, String publicId, String systemId) throws SAXException {
        StartDTDEvent event = new StartDTDEvent(name, publicId, systemId);
        events.add(event);
    }

    @Override
    public void endDTD() throws SAXException {
        EndDTDEvent event = new EndDTDEvent();
        events.add(event);
    }

    @Override
    public void startEntity(String name) throws SAXException {
        StartEntityEvent event = new StartEntityEvent(name);
        events.add(event);
    }

    @Override
    public void endEntity(String name) throws SAXException {
        EndEntityEvent event = new EndEntityEvent(name);
        events.add(event);
    }

    @Override
    public void startCDATA() throws SAXException {
        StartCDATAEvent event = new StartCDATAEvent();
        events.add(event);
    }

    @Override
    public void endCDATA() throws SAXException {
        EndCDATAEvent event = new EndCDATAEvent();
        events.add(event);
    }

    @Override
    public void comment(char[] ch, int start, int length) throws SAXException {
        CommentEvent event = new CommentEvent(ch, start, length);
        events.add(event);
    }

    protected UnmarshalRecord getParent() {
        return parent;
    }

    protected List getEvents() {
        return events;
    }

    // Made static final for performance reasons.
    /**
     * Implementation of Attributes - used to pass along a given node's attributes
     * to the startElement method of the reader's content handler.
     */
    private static final class AttributeList implements org.xml.sax.Attributes {

      private String[] localNames;
      private String[] uris;
      private String[] values;
      private String[] types;
      private ArrayList<String> qNames;

        public AttributeList(int size) {
          qNames = new ArrayList(size);
          localNames = new String[size];
          uris = new String[size];
          types= new String[size];
          values = new String[size];
        }

        public void addAttribute(String localName, String qName, String uri, String type, String value, int index) {
          qNames.add(index, qName);
          localNames[index] = localName;
          uris[index] = uri;
          types[index] = type;
          values[index] = value;
        }

        @Override
        public String getQName(int index) {
            return qNames.get(index);
        }

        @Override
        public String getType(String namespaceUri, String localName) {

            for(int i=0;i <localNames.length; i++){
                String nextLocalName = localNames[i];
                if(nextLocalName != null && localName!= null && localName.equals(nextLocalName)){
               String uriAtIndex = uris[i];
               if(uriAtIndex == null) {
                   uriAtIndex="";
               }
               if(uriAtIndex.equals(namespaceUri)){
                  return types[i];
                    }
                }
            }
           return null;

        }

        @Override
        public String getType(int index) {
          return types[index];
        }

        @Override
        public String getType(String qname) {
          return types[getIndex(qname)];
        }

        @Override
        public int getIndex(String qname) {
            return qNames.indexOf(qname);
        }

        @Override
        public int getIndex(String uri, String localName) {

             for(int i=0;i <localNames.length; i++){
                 String nextLocalName = localNames[i];
                 if(nextLocalName != null && localName!= null && localName.equals(nextLocalName)){
                     String uriAtIndex = uris[i];
                     if(uriAtIndex == null) {
                         uriAtIndex="";
                     }
                     if(uriAtIndex.equals(uri)){
                         return i;
                     }
                 }
             }
            return -1;
        }

        @Override
        public int getLength() {
            return localNames.length;
        }

        @Override
        public String getLocalName(int index) {
            return localNames[index];
        }

        @Override
        public String getURI(int index) {
            return uris[index];
        }

        @Override
        public String getValue(int index) {
               return values[index];
        }

        @Override
        public String getValue(String qname) {
          return values[getIndex(qname)];
        }

        @Override
        public String getValue(String uri, String localName) {
         for(int i=0;i <localNames.length; i++){
             String nextLocalName = localNames[i];
             if(nextLocalName != null && localName!= null && localName.equals(nextLocalName)){
                 String uriAtIndex = uris[i];
                 //handle null/empty namespace case
                 if(uriAtIndex == null) {
                     uriAtIndex="";
                 }
                 if(uriAtIndex.equals(uri)){
                     return values[i];
                 }
             }
         }
         return null;
        }

    }
}
