/*
 * 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 SF 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.felix.hc.generalchecks.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.felix.hc.api.FormattingResultLog;
import org.apache.felix.hc.api.Result;
import org.apache.felix.hc.api.ResultLog;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

/** Script Helper to simplify interaction with scripting engines in OSGi context. Used by ScriptedHealthCheck and can be used by other custom checks that want to allow to evaluate expressions via a scripting engine. */
public class ScriptHelper {

    public String getFileContents(String url) {
        String content;
        try {
            URLConnection conn = new URL(url).openConnection();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
                content = reader.lines().collect(Collectors.joining("\n"));
            }
            return content;
        }catch(IOException e) {
            throw new IllegalArgumentException("Could not read URL "+url+": "+e, e);
        }
    }
    
    public ScriptEngine getScriptEngine(ScriptEnginesTracker scriptEnginesTracker, String language) {
        ScriptEngine scriptEngine = scriptEnginesTracker.getEngineByLanguage(language);
        if(scriptEngine == null) {
            throw new IllegalArgumentException("No ScriptEngineFactory found for language "+ language + " (available languages: "+scriptEnginesTracker.getLanguagesByBundle()+")");
        }
        return scriptEngine;
    }
    
    public Object evalScript(BundleContext bundleContext, ScriptEngine scriptEngine, String scriptToExecute, FormattingResultLog log, Map<String,Object> additionalBindings, boolean logScriptResult) throws ScriptException, IOException {

        final Bindings bindings = new SimpleBindings();
        final ScriptHelperBinding scriptHelper = new ScriptHelperBinding(bundleContext);

        StringWriter stdout = new StringWriter();
        StringWriter stderr = new StringWriter();

        bindings.put("scriptHelper", scriptHelper);
        bindings.put("osgi", scriptHelper); // also register script helper like in web console script console
        bindings.put("log", log);
        bindings.put("bundleContext", bundleContext);
        if (additionalBindings != null) {
            for (Map.Entry<String, Object> additionalBinding : additionalBindings.entrySet()) {
                bindings.put(additionalBinding.getKey(), additionalBinding.getValue());
            }
        }
        
        SimpleScriptContext scriptContext = new SimpleScriptContext();
        scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
        scriptContext.setWriter(stdout);
        scriptContext.setErrorWriter(stderr);

        try {
            log.debug(scriptToExecute);
            Object scriptResult = scriptEngine.eval(scriptToExecute, scriptContext);
            appendStreamsToResult(log, stdout, stderr, scriptContext);

            if(scriptResult instanceof Result) {
                Result result = (Result) scriptResult;
                for(ResultLog.Entry entry: result) {
                    log.add(entry);
                }
            } else if(scriptResult != null && logScriptResult){
                log.info("Script result: {}", scriptResult);
            }
            
            return scriptResult;
        } finally  {
            scriptHelper.ungetServices();
        }
    }

    
    
    private void appendStreamsToResult(FormattingResultLog log, StringWriter stdout, StringWriter stderr, SimpleScriptContext scriptContext)
            throws IOException {
        scriptContext.getWriter().flush();
        String stdoutStr = stdout.toString();
        if(StringUtils.isNotBlank(stdoutStr)) {
            log.info("stdout of script: {}", stdoutStr);
        }
        
        scriptContext.getErrorWriter().flush();
        String stderrStr = stderr.toString();
        if(StringUtils.isNotBlank(stderrStr)) {
            log.critical("stderr of script: {}", stderrStr);
        }
    }

    // Script Helper for OSGi available as binding 'scriptHelper'
    class ScriptHelperBinding {
        
        private final BundleContext bundleContext;
        private List<ServiceReference<?>> references;
        private Map<String, Object> services;

        public ScriptHelperBinding(BundleContext bundleContext) {
            this.bundleContext = bundleContext;
        }

        @SuppressWarnings("unchecked")
        public <ServiceType> ServiceType getService(Class<ServiceType> type) {
            ServiceType service = (this.services == null ? null  : (ServiceType) this.services.get(type.getName()));
            if (service == null) {
                final ServiceReference<?> ref = this.bundleContext.getServiceReference(type.getName());
                if (ref != null) {
                    service = (ServiceType) this.bundleContext.getService(ref);
                    if (service != null) {
                        if (this.services == null) {
                            this.services = new HashMap<String, Object>();
                        }
                        if (this.references == null) {
                            this.references = new ArrayList<ServiceReference<?>>();
                        }
                        this.references.add(ref);
                        this.services.put(type.getName(), service);
                    }
                }
            }
            return service;
        }

        public <T> T[] getServices(Class<T> serviceType,  String filter) throws InvalidSyntaxException {
            final ServiceReference<?>[] refs = this.bundleContext.getServiceReferences(serviceType.getName(), filter);
            T[] result = null;
            if (refs != null) {
                final List<T> objects = new ArrayList<T>();
                for (int i = 0; i < refs.length; i++) {
                    @SuppressWarnings("unchecked")
                    final T service = (T) this.bundleContext.getService(refs[i]);
                    if (service != null) {
                        if (this.references == null) {
                            this.references = new ArrayList<ServiceReference<?>>();
                        }
                        this.references.add(refs[i]);
                        objects.add(service);
                    }
                }
                if (objects.size() > 0) {
                    @SuppressWarnings("unchecked")
                    T[] srv = (T[]) Array.newInstance(serviceType,  objects.size());
                    result = objects.toArray(srv);
                }
            }
            return result;
        }

        public void ungetServices() {
            if (this.references != null) {
                final Iterator<ServiceReference<?>> i = this.references.iterator();
                while (i.hasNext()) {
                    final ServiceReference<?> ref = i.next();
                    this.bundleContext.ungetService(ref);
                }
                this.references.clear();
            }
            if (this.services != null) {
                this.services.clear();
            }
        }
    }
    
}
