/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package org.netbeans.modules.properties;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Position;
import org.openide.text.PositionRef;
import org.openide.text.PositionBounds;


/**
 * Parser of .properties files. It generates structure of comment-key-vaue property elements.
 *
 * @author Petr Jiricka, Petr Hamernik, Peter Zavadsky
 * @see PropertiesStructure
 * @see Element.ItemElem
 */
class PropertiesParser {

    /** PropertiesFileEntry for which source is this parser created. */
    PropertiesFileEntry pfe;

    /** Appropriate properties editor - used for creating the PositionRefs */
    PropertiesEditorSupport editor;

    /** Properties file reader. Input stream. */
    PropertiesReader propertiesReader;
    
    /** Flag if parsing should be stopped. */
    private boolean stop = false;

    
    /** 
     * Creates parser. Has to be {@link init} afterwards.
     * @param pfe FileEntry where the properties file is stored.
     */
    public PropertiesParser(PropertiesFileEntry pfe) {
        this.pfe   = pfe;
    }

    
    /** Inits parser.
     * @exception IOException if any i/o problem occured during reading */
    void initParser() throws IOException {
        editor = pfe.getPropertiesEditor();
        propertiesReader = createReader();
    }
    
    /** Creates new input stream from the file object.
     * Finds the properties data object, checks if the document is loaded,
     * if not is loaded and created a stream from the document.
     * @exception IOException if any i/o problem occured during reading
     */
    private PropertiesReader createReader() throws IOException {
        // Get loaded document, or load it if necessary.
        Document loadDoc = null;
        
        if(editor.isDocumentLoaded()) {
            loadDoc = editor.getDocument();
        } 
    
        if(loadDoc == null) {
            loadDoc = editor.openDocument(); 
        }
            
        final Document document = loadDoc;
        final String[] str = new String[1];

        // safely take the text from the document
        document.render(new Runnable() {
            public void run() {
                try {
                    str[0] = document.getText(0, document.getLength());
                } catch(BadLocationException ble) {
                    // Should be not possible.
                    ble.printStackTrace();
                }
            }
        });

        return new PropertiesReader(str[0]);
    }

    /** Parses .properties file specified by <code>pfe</code> and resets its properties
     * structure.
     * @return new properties structure or null if parsing failed
     */
    public PropertiesStructure parseFile() {
        try {
            PropertiesStructure propStructure = parseFileMain();
            
            return propStructure;
        } catch(IOException e) {
            // Parsing failed, return null.
            return null;
        }
    }
    
    /** Stops parsing. */
    public void stop() {
        stop = true;
        clean();
    }
    
    /** Provides clean up after finish parsing. */
    public void clean() {
        if(propertiesReader != null) {
            try {
                propertiesReader.close();
                propertiesReader = null;
            } catch(IOException ioe) {
                org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ioe);
            }
        }
    }

    /** Parses .properties file and creates <code>PropertiesStruture</code>. */
    private PropertiesStructure parseFileMain() throws IOException {

        Map<String,Element.ItemElem> items = new HashMap<String,Element.ItemElem>(25, 1.0F);

        PropertiesReader reader = null;
        
        while (true) {
            if (stop) {
                // Parsing stopped -> return immediatelly.
                return null;
            }
            
            reader = propertiesReader;
            if (reader == null) {
                // Parsing was stopped.
                return null;
            }
            Element.ItemElem element = readNextElem(reader);
            
            if (element == null) {
                break;
            } else {
                // add at the end of the list
                items.put(element.getKey(), element);
            }
        }
        
        return new PropertiesStructure(createBiasBounds(0, reader.position), items);
    }

    /**
     * Reads next element from input stream. 
     * @return next element or null if the end of the stream occurred */
    private Element.ItemElem readNextElem(PropertiesReader in) throws IOException {
        Element.CommentElem commE;
        Element.KeyElem keyE;
        Element.ValueElem valueE;

        int begPos = in.position;

        // read the comment
        int keyPos = begPos;
        FlaggedLine fl = in.readLineExpectComment();
        StringBuffer comment = new StringBuffer();
        boolean firstNull = true;
        while (fl != null) {
            firstNull = false;
            if(fl.flag) {
                //part of the comment
                comment.append(trimComment(fl.line));
                comment.append(fl.lineSep);
                keyPos = in.position;
            } else
                // not a part of a comment
                break;
            fl = in.readLineExpectComment();
        }

        // exit completely if null is returned the very first time
        if (firstNull) {
            return null;
        }

        String comHelp;
        comHelp = comment.toString();
        if(comment.length() > 0)
            if(comment.charAt(comment.length() - 1) == '\n')
                comHelp = comment.substring(0, comment.length() - 1);

        commE = new Element.CommentElem(createBiasBounds(begPos, keyPos), UtilConvert.loadConvert(comHelp));
        // fl now contains the line after the comment or  null if none exists


        if(fl == null) {
            keyE = null;
            valueE = null;
        } else {
            // read the key and the value
            // list of
            ArrayList<FlaggedLine> lines = new ArrayList<FlaggedLine>(2);
            fl.startPosition = keyPos;
            fl.stringValue = fl.line.toString();
            lines.add(fl);
            int nowPos;
            while (isPartialLine(fl.line)) {
                // do something with the previous line
                fl.stringValue = fl.stringValue.substring(0, fl.stringValue/*fix: was: line*/.length() - 1);
                // now the new line
                nowPos = in.position;
                fl = in.readLineNoFrills();
                if(fl == null) break;
                // delete the leading whitespaces
                int startIndex=0;
                for(startIndex=0; startIndex < fl.line.length(); startIndex++)
                    if(UtilConvert.whiteSpaceChars.indexOf(fl.line.charAt(startIndex)) == -1)
                        break;
                fl.stringValue = fl.line.substring(startIndex, fl.line.length());
                fl.startPosition = nowPos + startIndex;
                lines.add(fl);
            }
            // now I have an ArrayList with strings representing lines and positions of the first non-whitespace character

            PositionMap positionMap = new PositionMap(lines);
            String line = positionMap.getString();

            // Find start of key
            int len = line.length();
            int keyStart;
            for(keyStart=0; keyStart<len; keyStart++) {
                if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1)
                    break;
            }
            
            // Find separation between key and value
            int separatorIndex;
            for(separatorIndex=keyStart; separatorIndex<len; separatorIndex++) {
                char currentChar = line.charAt(separatorIndex);
                if(currentChar == '\\')
                    separatorIndex++;
                else if(UtilConvert.keyValueSeparators.indexOf(currentChar) != -1)
                    break;
            }

            // Skip over whitespace after key if any
            int valueIndex;
            for (valueIndex=separatorIndex; valueIndex<len; valueIndex++)
                if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
                    break;

            // Skip over one non whitespace key value separators if any
            if(valueIndex < len)
                if(UtilConvert.strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1)
                    valueIndex++;

            // Skip over white space after other separators if any
            while (valueIndex < len) {
                if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)
                    break;
                valueIndex++;
            }
            String key = line.substring(keyStart, separatorIndex);
            String value = (separatorIndex < len) ? line.substring(valueIndex, len) : ""; // NOI18N

            if(key == null)
                // PENDING - should join with the next comment
                ;

            int currentPos = in.position;
            int valuePosFile = 0;
            
            try {
                valuePosFile = positionMap.getFilePosition(valueIndex);
            } catch (ArrayIndexOutOfBoundsException e) {
                valuePosFile = currentPos;
            }
            
            keyE   = new Element.KeyElem  (createBiasBounds(keyPos, valuePosFile), UtilConvert.loadConvert(key));
            valueE = new Element.ValueElem(createBiasBounds(valuePosFile, currentPos), UtilConvert.loadConvert(value));
        }
        
        return new Element.ItemElem(createBiasBounds(begPos, in.position), keyE, valueE, commE);
    }

    /** Remove leading comment markers. */
    private StringBuffer trimComment(StringBuffer line) {
        while (line.length() > 0) {
            char lead = line.charAt(0);
            if (lead == '#' || lead == '!') {
                line.deleteCharAt(0);
            } else {
                break;
            }
        }
        return line;
    }

    /** Utility method. Computes the real offset from the long value representing position in the parser.
     * @return the offset
     */
    private static int position(long p) {
        return (int)(p & 0xFFFFFFFFL);
    }

    /** Creates position bounds. For obtaining the real offsets is used
     * previous method position()
     * @param begin the begin in the internal position form
     * @param end the end in the internal position form
     * @return the bounds
     */
    private PositionBounds createBiasBounds(long begin, long end) {
        PositionRef posBegin = editor.createPositionRef(position(begin), Position.Bias.Forward);
        PositionRef posEnd = editor.createPositionRef(position(end), Position.Bias.Backward);
        return new PositionBounds(posBegin, posEnd);
    }

    /** 
     * Properties reader which allows reading from an input stream or from a string and remembers
     * its position in the document.
     */
    private static class PropertiesReader extends BufferedReader {

        /** Name constant of line separator system property. */
        private static final String LINE_SEPARATOR = "line.separator"; // NOI18N
        
        /** The character that someone peeked. */
        private int peekChar = -1;
        
        /** Position after the last character read. */
        public int position = 0;


        /** Creates <code>PropertiesReader</code> from buffer. */
        private PropertiesReader(String buffer) {
            super(new StringReader(buffer));
        }

        /** Creates <code>PropertiesReader</code> from another reader. */
        private PropertiesReader(Reader reader) {
            super(reader);
        }
        
        
        /** Read one character from the stream and increases the position.
         * @return the character or -1 if the end of the stream has been reached
         */
        public int read() throws IOException {
            int character = peek();
            peekChar = -1;
            if(character != -1)
                position++;

            return character;
        }

        /** Returns the next character without increasing the position. Subsequent calls
         * to peek() and read() will return the same character.
         * @return the character or -1 if the end of the stream has been reached
         */
        private int peek() throws IOException {
            if(peekChar == -1)
                peekChar = super.read();
            
            return peekChar;
        }

        /** Reads the next line and returns the flag as true if the line is a comment line.
         *  If the input is empty returns null
         *  Flag in the result is true if the line is a comment line
         */
        public FlaggedLine readLineExpectComment() throws IOException {
            int charRead = read();
            if(charRead == -1)
                // end of the reader reached
                return null;

            boolean decided = false;
            FlaggedLine fl = new FlaggedLine();
            while (charRead != -1 && charRead != (int)'\n' && charRead != (int)'\r') {
                if(!decided)
                    if(UtilConvert.whiteSpaceChars.indexOf((char)charRead) == -1) {
                        // not a whitespace - decide now
                        fl.flag = (((char)charRead == '!') || ((char)charRead == '#'));
                        decided = true;
                    }
                fl.line.append((char)charRead);
                charRead = read();
            }

            if(!decided)
                // all were whitespaces
                fl.flag = true;

            // set the line separator
            if(charRead == (int)'\r')
                if(peek() == (int)'\n') {
                    charRead = read();
                    fl.lineSep = "\r\n"; // NOI18N
                } else
                    fl.lineSep = "\r"; // NOI18N
            else
                if(charRead == (int)'\n') 
                    fl.lineSep = "\n"; // NOI18N
                else
                    fl.lineSep = System.getProperty(LINE_SEPARATOR);

            return fl;
        }

        /** Reads the next line. 
         * @return <code>FlaggedLine</code> or null if the input is empty */
        public FlaggedLine readLineNoFrills() throws IOException {
            int charRead = read();
            if(charRead == -1)
                // end of the reader reached
                return null;

            FlaggedLine fl = new FlaggedLine();
            while (charRead != -1 && charRead != (int)'\n' && charRead != (int)'\r') {
                fl.line.append((char)charRead);
                charRead = read();
            }

            // set the line separator
            if(charRead == (int)'\r')
                if(peek() == (int)'\n') {
                    charRead = read();
                    fl.lineSep = "\r\n"; // NOI18N
                } else
                    fl.lineSep = "\r"; // NOI18N
            else
                if(charRead == (int)'\n') // NOI18N
                    fl.lineSep = "\n"; // NOI18N
                else
                    fl.lineSep = System.getProperty(LINE_SEPARATOR);

            return fl;
        }

    } // End of nested class PropertiesReader.

    /**
     * Returns true if the given line is a line that must
     * be appended to the next line
     */
    private static boolean isPartialLine (StringBuffer line) {
        int slashCount = 0;
        int index = line.length() - 1;
        while((index >= 0) && (line.charAt(index--) == '\\'))
            slashCount++;
        return (slashCount % 2 == 1);
    }

    /** Nested class which maps positions in a string to positions in the underlying file.
     * @see FlaggedLine */
    private static class PositionMap {

        /** List of <code>FlaggedLine</code>'s. */
        private List<FlaggedLine> list;
        
        
        /** Constructor - expects a list of FlaggedLine */
        PositionMap(List<FlaggedLine> lines) {
            list = lines;
        }
        

        /** Returns the string represented by the object */
        public String getString() {
            String allLines = list.get(0).stringValue;
            for (int part=1; part<list.size(); part++) {
                allLines += list.get(part).stringValue;
            }
            return allLines;
        }

        /** Returns position in the file for a position in a string
         * @param posString position in the string to find file position for
         * @return position in the file 
         * @exception ArrayIndexOutOfBoundsException if the requested position is outside 
         * the area represented by this object
         */                  
        public int getFilePosition(int posString) throws ArrayIndexOutOfBoundsException {
            // get the part
            int part;
            int lengthSoFar = 0;
            int lastLengthSoFar = 0;
            for (part=0; part < list.size(); part++) {
                lastLengthSoFar = lengthSoFar;
                lengthSoFar += list.get(part).stringValue.length();
                // brute patch - last (cr)lf should not be the part of the thing, other should
                if (part == list.size() - 1) {
                    if (lengthSoFar >= posString) {
                        break;
                    }
                } else {
                    if (lengthSoFar > posString) {
                        break;
                    }
                }
            }
            if (posString > lengthSoFar) {
                throw new ArrayIndexOutOfBoundsException("not in scope"); // NOI18N
            }
            return list.get(part).startPosition + posString - lastLengthSoFar;
        }
    } // End of nested class PositionMap.

    
    /** Helper nested class. */
    private static class FlaggedLine {

        /** Line buffer. */
        StringBuffer line;
        
        /** Flag. */
        boolean flag;
        
        /** Line separator. */
        String lineSep;
        
        /** Start position. */
        int startPosition;
        
        /** Value. */
        String stringValue;

        
        /** Constructor. */
        FlaggedLine() {
            line = new StringBuffer();
            flag = false;
            lineSep = "\n"; // NOI18N
            startPosition = 0;
        }
    } // End of nested class FlaggedLine.
}
