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

import org.apache.mrql.gen.*;


/** Provides the API for compilation/code-generation */
final public class TopLevel extends Interpreter {
    static Tree xml_type;

    public TopLevel () {
        // XML and JSON are user-defined types:
        datadef("XML",#<union(Node(tuple(string,bag(tuple(string,string)),list(XML))),
                              CData(string))>);
        datadef("JSON",#<union(JObject(bag(tuple(string,JSON))),
                               JArray(list(JSON)),
                               Jstring(string),
                               Jlong(long),
                               Jdouble(double),
                               Jbool(bool),
                               Jnull(tuple()))>);
        constant(#<PI>,#<double>,new MR_double(Math.PI));
        xml_type = global_datatype_env.lookup("XML");
        DataSource.loadParsers();
    }

    private static boolean memory_parsed_source ( Tree e ) {
        match e {
        case ParsedSource(...): return true;
        case Merge(`x,`y): return memory_parsed_source(x) && memory_parsed_source(y);
        };
        return false;
    }

    /** translate and evaluate an MRQL expression into MRData
     * @param e MRQL query to be evaluated
     * @param print do we want to print the result?
     * @return the result of evaluation (MRData)
     */
    public static MRData expression ( Tree e, boolean print ) {
        try {
            Tree plan = translate_expression(e);
            query_plan = plan;
            tab_count = -3;
            if (plan == null)
                return null;
            if (Config.hadoop_mode)
                Evaluator.evaluator.initialize_query();
            MRData res = evalE(plan,null);
            if (print) {
                if (!Config.quiet_execution)
                    System.out.println("Result:");
                if (!Config.hadoop_mode && Config.bsp_mode && memory_parsed_source(plan))
                    System.out.println(print(((Tuple)((Bag)res).get(0)).second(),query_type));
                else System.out.println(print(res,query_type));
            } return res;
        } catch (Exception x) {
            if (x.getMessage() != null)
                System.err.println("*** MRQL System Error at line "+Main.parser.line_pos()+": "+x);
            if (Config.trace)
                x.printStackTrace(System.err);
            if (Config.testing)
                throw new Error(x);
            return null;
        } catch (Error x) {
            if (x.getMessage() != null)
                System.err.println("*** MRQL System Error at line "+Main.parser.line_pos()+": "+x);
            if (Config.trace)
                x.printStackTrace(System.err);
            if (Config.testing)
                throw new Error(x);
            return null;
        }
    }

    /** translate, evaluate, and print the results of an MRQL expression e
     * @param e MRQL query to be evaluated
     * @return the result of evaluation (MRData)
     */
    public final static MRData expression ( Tree e ) {
        reset();
        return expression(e,true);
    }

    /** handle the assignment v=e */
    public final static void assign ( String v, Tree e ) {
        if (variable_lookup(v,global_env) != null) {
            global_type_env.remove(v);
            remove_global_binding(v);
        };
        global_vars.insert(v,e);
    }

    private final static boolean is_function ( Tree e ) {
        match e {
        case function(...): return true;
        };
        return false;
    }

    /** handle the assignment v:=e */
    public final static Tree distributed_assign ( String v, Tree e ) {
        reset();
        if (global_vars.lookup(v) != null)
            global_vars.remove(v);
        MRData res = expression(e,false);
        global_type_env.insert(v,query_type);
        if (res instanceof Bag)
            ((Bag)res).materialize();
        new_distributed_binding(v,res);
        return query_plan;
    }

    /** bind v to the result of e */
    public final static Tree store ( String v, Tree e ) {
        reset();
        if (global_vars.lookup(v) != null)
            global_vars.remove(v);
        MRData res = expression(e,false);
        global_type_env.insert(v,query_type);
        if (res instanceof Bag)
            ((Bag)res).materialize();
        new_global_binding(v,res);
        return query_plan;
    }

    /** define an MRQL constant, such as PI */
    private final static void constant ( Tree v, Tree type, MRData value ) {
        String var = v.toString();
        if (global_vars.lookup(var) != null)
            global_vars.remove(var);
        global_type_env.insert(var,type);
        new_global_binding(var,value);
    }

    /** define a new function
     * @param fnc function name
     * @param params parameter list
     * @param out_type output type
     * @param body function body
     */
    public final static void functiondef ( String fnc, Trees params, Tree out_type, Tree body ) {
        reset();
        Trees as = #[];
        Trees ps = #[];
        for ( Tree param: params )
            match param {
            case bind(`v,`tp):
                Tree ntp = normalize_type(tp);
                as = as.append(ntp);
                ps = ps.append(#<bind(`v,`ntp)>);
            case _: type_error(param,"Ill-formed function parameter: "+param);
            };
        out_type = normalize_type(out_type);
        // needed for recursive functions
        global_type_env.insert(fnc,#<arrow(tuple(...as),`out_type)>);
        Tree fname = #<`fnc>;
        if (!is_pure(body))
            impure_functions = impure_functions.append(fname);
        Tree plan = store(fnc,#<function(tuple(...ps),`out_type,`body)>);
        if (plan != null)
            Translator.global_functions.insert(fnc,plan);
        if (Config.hadoop_mode && plan != null)
            Plan.conf.set("mrql.global."+fnc,
                          closure(plan,global_env).toString());
    }

    /** dump the result of evaluating the MRQL query e to a binary file */
    private final static void dump ( String file, Tree e ) {
        MRData res = expression(e,false);
        try {
            query_type = make_persistent_type(query_type);
            if (res != null)
                if (Config.hadoop_mode) 
                    Evaluator.evaluator.dump(file,query_type,res);
                else MapReduceAlgebra.dump(file,query_type,res);
        } catch (Exception x) {
            throw new Error(x);
        }
    }

    /** dump the result of evaluating the MRQL query e to a text CVS file */
    private final static void dump_text ( String file, Tree e ) {
        MRData res = expression(e,false);
        if (res != null)
            try {
		Evaluator.evaluator.dump_text(file,query_type,res);
            } catch (Exception x) {
                throw new Error(x);
            }
    }

    /** define a new named type (typedef) */
    private final static void typedef ( String name, Tree type ) {
        type_names.insert(name,normalize_type(type));
    }

    /** define a new data type, such as XML and JSON */
    private final static void datadef ( String name, Tree type ) {
        int i = 0;
        Trees as = #[];
        match type {
        case union(...nl):
            // needed for recursive datatypes
            global_datatype_env.insert(name,#<union(...nl)>);
            for ( Tree n: nl )
                match n {
                case `c(`t):
                    if (data_constructors.lookup(c.toString()) == null)
                        data_constructors.insert(c.toString(),#<`name(`i,`t)>);
                    else type_error(type,"Data constructor "+c+" has already been defined");
                    as = as.append(#<`c(`(normalize_type(t)))>);
                    i++;
                }
        };
        global_datatype_env.remove(name);
        global_datatype_env.insert(name,#<union(...as)>);
    }

    /** define a user aggregation */
    private static void aggregation ( String name, Tree type, Tree plus, Tree zero, Tree unit ) {
        reset();
        zero = Simplification.rename(zero);
        plus = Simplification.rename(plus);
        unit = Simplification.rename(unit);
        type = normalize_type(type);
        Tree ztp = TypeInference.type_inference2(zero);
        Tree v1 = new_var();
        type_env.insert(v1.toString(),ztp);
        TypeInference.type_inference2(Normalization.normalize_all(#<apply(`plus,tuple(`v1,`v1))>));
        Tree v2 = new_var();
        type_env.insert(v2.toString(),type);
        Tree utp = TypeInference.type_inference2(Normalization.normalize_all(#<apply(`unit,`v2)>));
        if (unify(utp,ztp) == null)
            type_error(unit,"Wrong type in unit result (expected "+ztp+" found "+utp);
        monoids = monoids.append(#<`name(`type,`plus,`zero,`unit)>);
    }

    /** the MRQL top-level interfacse to evaluate a single MRQL expression or command */
    public final static void evaluate_top_level ( Tree expr ) {
        if (expr == null)
            return;
        match expr {
        case expression(`e):
            long t = System.currentTimeMillis();
            if (expression(e) != null && !Config.quiet_execution)
                System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
        case assign(`v,`e): assign(v.toString(),e);
        case store(`v,`e):
            long t = System.currentTimeMillis();
            if (distributed_assign(v.toString(),e) != null && !Config.quiet_execution)
                System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
        case dump(`s,`e):
            long t = System.currentTimeMillis();
            dump(s.stringValue(),e);
            if (!Config.quiet_execution)
                System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
        case dump_text(`s,`e):
            long t = System.currentTimeMillis();
            dump_text(s.stringValue(),e);
            if (!Config.quiet_execution)
                System.out.println("Run time: "+(System.currentTimeMillis()-t)/1000.0+" secs");
        case typedef(`v,`t): typedef(v.toString(),t);
        case datadef(`v,`t): datadef(v.toString(),t);
        case functiondef(`f,params(...p),`tp,`e):
            functiondef(f.toString(),p,tp,e);
        case macrodef(`name,params(...p),`e):
            Translator.global_macros.insert(name.toString(),#<macro(params(...p),`e)>);
        case aggregation(`aggr,`type,`plus,`zero,`unit):
            aggregation(aggr.toString(),type,plus,zero,unit);
        case import(`c):
            ClassImporter.importClass(c.variableValue());
        case import(`c,...l):
            for (Tree m: l)
                ClassImporter.importMethod(c.variableValue(),m.variableValue());
        case include(`file):
            Main.include_file(file.toString());
        case parser(`n,`p):
            try {
                Class<? extends Parser> c = Class.forName(p.toString()).asSubclass(Parser.class);
                DataSource.parserDirectory.put(n.toString(),c);
            } catch (ClassNotFoundException e) {
                throw new Error("Class "+p.toString()+" not found");
            }
        case impure(`fn):    // not used
            impure_functions = impure_functions.append(fn);
        case _: throw new Error("Unknown statement: "+expr);
        }
    }
}
