/*
 *  Copyright 2006-2008 Mikhail Kryshen
 *
 *  This file is part of Tema.
 *
 *  Tema is free software: you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  Tema is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the 
 *  GNU Lesser General Public License along with Tema.  
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 *  $Id: Define.java,v 1.25 2008/02/17 23:58:01 mikhail Exp $
 */

package kryshen.tema.functions;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import kryshen.tema.Context;
import kryshen.tema.Function;
import kryshen.tema.FunctionDataParser;
import kryshen.tema.TemplateException;
import kryshen.tema.TemplateParser;
import kryshen.tema.io.TemplateReader;

/**
 * Define function implementation.
 *
 * @author Mikhail Kryshen
 */
public class Define extends Function {
    public static final Function DEFINE = new Define();
    
    public Define() {
    }
    
    public int invoke(FunctionDataParser fdp, Writer out)
    throws IOException, TemplateException {
        
        StringWriter nameWriter = new StringWriter();
        int r = fdp.parseNextArg(nameWriter);
        
        if (r == 0)
            return 0;                
        
        StringWriter dataWriter = new StringWriter();
        r = fdp.parseData(dataWriter);
        
        if (r == 0)
            return 0;
               
        final String name = nameWriter.toString();
        final String data = dataWriter.toString();
        
        Function newFunction = new Function() {
            public int invoke(final FunctionDataParser fdp1, final Writer out)
            throws IOException, TemplateException {
                
                final TemplateParser functionParser =
                        new TemplateParser(fdp1.getTemplateParser());
                
                final Context functionContext = 
                        functionParser.getContext();                
                
                functionContext.set
                        ("next_arg", new Function() {
                    public int invoke(FunctionDataParser unusedFdp,
                            final Writer out)
                            throws IOException, TemplateException {
                        
                        if (fdp1.hasMoreData())
                            return fdp1.parseNextArg(out);
                        
                        return 0;
                    }
                });
                
                functionContext.set
                        ("data", new Function() {
                    public int invoke(FunctionDataParser unusedFdp,
                            final Writer out)
                            throws IOException, TemplateException {
                        
                        return fdp1.parseData(out);
                    }
                });
                
                functionContext.set
                        ("has_more_data", new Function() {
                    public int invoke(FunctionDataParser unusedFdp,
                            final Writer out)
                            throws IOException, TemplateException {
                        
                        if (fdp1.hasMoreData()) {
                            out.write("true");
                            return 1;
                        }
                        
                        out.write("false");
                        return 0;
                    }
                });
                
                TemplateReader dataReader = new TemplateReader
                        (new StringReader(data), fdp1.getTemplateReader());
                
                return functionParser.parse(dataReader, out);
            }
        };
        
        fdp.getContext().set(name, newFunction);
        
        out.write(name);
        return r;
    }
}