/*
 * 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.apache.jena.riot.process.normalize;

import static org.apache.jena.atlas.lib.Chars.CH_DOT ;
import static org.apache.jena.atlas.lib.Chars.CH_MINUS ;
import static org.apache.jena.atlas.lib.Chars.CH_PLUS ;
import org.apache.jena.datatypes.RDFDatatype ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.NodeFactory ;

class NormalizeValue2
{
    // faster (??)
    // faster - directly check for correct forms : leading zeros, signs.
    // Place into char[], zap with -1 if unwanted, recollect, rebuild string.
    
    // --- Unfinished
    
    static char NonChar = (char)0 ;
    static char CH_ZERO = '0' ;
    
    private static void stripLeadingPlus(char[] chars)
    {
        if ( chars[0] == CH_PLUS )
            chars[0] = NonChar ;
    }
    
    // Works on decimals and integers as "." is "just" a stopping character.
    private static void stripLeadingZeros(char[] chars)
    {
        // Avoid sign, or zapped sign.
        int idx = 0 ;
        if ( chars[0] == CH_MINUS || chars[0] == NonChar )
            idx = 1 ;
        // BUT not all zeros.
        while( idx < chars.length && chars[idx] == CH_ZERO )
        {
            chars[idx] = NonChar ;
            idx ++ ;
        }
        // All leading zeros - put one back.
        // what about "-.1"?
        if ( idx == chars.length || chars[idx] == '.' )
            chars[idx-1] = CH_ZERO ;
        
    }
    
    // Decimal specific.
    private static void stripTrailingZeros(char[] chars)
    {
        // Find the . (if any)
        int iDot = 0 ;
        for ( ; iDot < chars.length ; iDot++ )
        {
            if ( chars[iDot] == CH_DOT ) 
                break ;
        }
        
        if ( iDot == chars.length )
            // No dot.
            // ??
            {}
        
        int start = 0 ;
        if ( chars[0] == CH_MINUS || chars[0] == NonChar )
            start = 1 ;

        int idx ;
        for ( idx = chars.length-1 ; idx >= start ; idx-- )
        {
            if ( chars[idx] != CH_ZERO )
                break ;
            chars[idx] = NonChar ;
        }
        // Don't remove all trailing zeros if "123." or "000"  
        if ( idx == start || chars[idx] == '.' )
            chars[idx-1] = CH_ZERO ;
    }

    // Rebuild a string but return null for "no change"
    private static String rebuild(char[] chars)
    {
        // i is the read index, j the write index.
        boolean modified = false ;
        int j = 0 ;
        for ( int i = 0 ; i < chars.length ; i++)
        {
            if ( chars[i] == NonChar )
            {
                modified = true ;
                continue ;
            }
            if ( ! modified )
                continue ;
            chars[j] = chars[i] ;
            j++ ;
        }
        if ( ! modified )
            return null ;
        return new String(chars,0,j) ;
    }
    
    // --- Working versions 
    
    static DatatypeHandler dtInteger = (Node node, String lexicalForm, RDFDatatype datatype) -> {
        char[] chars = lexicalForm.toCharArray() ;
        if ( chars.length == 0 )
            // Illegal lexical form.
            return node ;
        stripLeadingPlus(chars) ;
        stripLeadingZeros(chars) ;
        String lex2 = rebuild(chars) ;
        if ( lex2 == null )
            return node ;
        return NodeFactory.createLiteral(lex2, datatype) ;
    } ;

    static DatatypeHandler dtDecimal = (Node node, String lexicalForm, RDFDatatype datatype) -> {
        // Need to force "0."
        char[] chars = lexicalForm.toCharArray() ;
        if ( chars.length == 0 )
            // Illegal lexical form.
            return node ;
        stripLeadingPlus(chars) ;
        stripLeadingZeros(chars) ;
        stripTrailingZeros(chars) ;
        String lex2 = rebuild(chars) ;
        if ( lex2 == null )
            return node ;
        return NodeFactory.createLiteral(lex2, datatype) ;
    } ;
}
