/**
 * 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.storm.hive.bolt;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.tuple.Tuple;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.utils.TupleUtils;
import backtype.storm.Config;
import org.apache.storm.hive.common.HiveWriter;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.hive.hcatalog.streaming.*;
import org.apache.storm.hive.common.HiveOptions;
import org.apache.storm.hive.common.HiveUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.List;
import java.util.LinkedList;
import java.io.IOException;

public class HiveBolt extends  BaseRichBolt {
    private static final Logger LOG = LoggerFactory.getLogger(HiveBolt.class);
    private OutputCollector collector;
    private HiveOptions options;
    private ExecutorService callTimeoutPool;
    private transient Timer heartBeatTimer;
    private Boolean kerberosEnabled = false;
    private AtomicBoolean timeToSendHeartBeat = new AtomicBoolean(false);
    private UserGroupInformation ugi = null;
    HashMap<HiveEndPoint, HiveWriter> allWriters;
    private List<Tuple> tupleBatch;

    public HiveBolt(HiveOptions options) {
        this.options = options;
        tupleBatch = new LinkedList<>();
    }

    @Override
    public void prepare(Map conf, TopologyContext topologyContext, OutputCollector collector)  {
        try {
            if(options.getKerberosPrincipal() == null && options.getKerberosKeytab() == null) {
                kerberosEnabled = false;
            } else if(options.getKerberosPrincipal() != null && options.getKerberosKeytab() != null) {
                kerberosEnabled = true;
            } else {
                throw new IllegalArgumentException("To enable Kerberos, need to set both KerberosPrincipal " +
                                                   " & KerberosKeytab");
            }

            if (kerberosEnabled) {
                try {
                    ugi = HiveUtils.authenticate(options.getKerberosKeytab(), options.getKerberosPrincipal());
                } catch(HiveUtils.AuthenticationFailed ex) {
                    LOG.error("Hive Kerberos authentication failed " + ex.getMessage(), ex);
                    throw new IllegalArgumentException(ex);
                }
            }
            this.collector = collector;
            allWriters = new HashMap<HiveEndPoint,HiveWriter>();
            String timeoutName = "hive-bolt-%d";
            this.callTimeoutPool = Executors.newFixedThreadPool(1,
                                new ThreadFactoryBuilder().setNameFormat(timeoutName).build());
            heartBeatTimer = new Timer();
            setupHeartBeatTimer();

            // If interval is non-zero then it has already been explicitly set and we should not default it
            if (conf.containsKey("topology.message.timeout.secs") && options.getTickTupleInterval() == 0)
            {
                Integer topologyTimeout = Integer.parseInt(conf.get("topology.message.timeout.secs").toString());
                int tickTupleInterval = (int) (Math.floor(topologyTimeout / 2));
                options.withTickTupleInterval(tickTupleInterval);
                LOG.debug("Setting tick tuple interval to [" + tickTupleInterval + "] based on topology timeout");
            }
        } catch(Exception e) {
            LOG.warn("unable to make connection to hive ", e);
        }
    }

    @Override
    public void execute(Tuple tuple) {
        try {
            boolean forceFlush = false;
            if (TupleUtils.isTick(tuple)) {
                LOG.debug("TICK received! current batch status [" + tupleBatch.size() + "/" + options.getBatchSize() + "]");
                forceFlush = true;
            }
            else {
                List<String> partitionVals = options.getMapper().mapPartitions(tuple);
                HiveEndPoint endPoint = HiveUtils.makeEndPoint(partitionVals, options);
                HiveWriter writer = getOrCreateWriter(endPoint);
                if (timeToSendHeartBeat.compareAndSet(true, false)) {
                    enableHeartBeatOnAllWriters();
                }
                writer.write(options.getMapper().mapRecord(tuple));
                tupleBatch.add(tuple);
                if (tupleBatch.size() >= options.getBatchSize())
                    forceFlush = true;
            }
            if(forceFlush && !tupleBatch.isEmpty()) {
                flushAllWriters(true);
                LOG.info("acknowledging tuples after writers flushed ");
                for(Tuple t : tupleBatch)
                    collector.ack(t);
                tupleBatch.clear();
            }
        } catch(Exception e) {
            this.collector.reportError(e);
            collector.fail(tuple);
            try {
                flushAndCloseWriters();
                LOG.info("acknowledging tuples after writers flushed and closed");
                for (Tuple t : tupleBatch)
                    collector.ack(t);
                tupleBatch.clear();
            } catch (Exception e1) {
                //If flushAndClose fails assume tuples are lost, do not ack
                LOG.warn("Error while flushing and closing writers, tuples will NOT be acknowledged");
                for (Tuple t : tupleBatch)
                    collector.fail(t);
                tupleBatch.clear();
            }
        }
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {

    }

    @Override
    public void cleanup() {
        for (Entry<HiveEndPoint, HiveWriter> entry : allWriters.entrySet()) {
            try {
                HiveWriter w = entry.getValue();
                LOG.info("Flushing writer to {}", w);
                w.flush(false);
                LOG.info("Closing writer to {}", w);
                w.close();
            } catch (Exception ex) {
                LOG.warn("Error while closing writer to " + entry.getKey() +
                         ". Exception follows.", ex);
                if (ex instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                }
            }
        }

        ExecutorService toShutdown[] = {callTimeoutPool};
        for (ExecutorService execService : toShutdown) {
            execService.shutdown();
            try {
                while (!execService.isTerminated()) {
                    execService.awaitTermination(
                                 options.getCallTimeOut(), TimeUnit.MILLISECONDS);
                }
            } catch (InterruptedException ex) {
                LOG.warn("shutdown interrupted on " + execService, ex);
            }
        }
        callTimeoutPool = null;
        super.cleanup();
        LOG.info("Hive Bolt stopped");
    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        Map<String, Object> conf = super.getComponentConfiguration();
        if (conf == null)
            conf = new Config();

        if (options.getTickTupleInterval() > 0)
            conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, options.getTickTupleInterval());

        return conf;
    }

    private void setupHeartBeatTimer() {
        if(options.getHeartBeatInterval()>0) {
            heartBeatTimer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        timeToSendHeartBeat.set(true);
                        setupHeartBeatTimer();
                    }
                }, options.getHeartBeatInterval() * 1000);
        }
    }

    void flushAllWriters(boolean rollToNext)
        throws HiveWriter.CommitFailure, HiveWriter.TxnBatchFailure, HiveWriter.TxnFailure, InterruptedException {
        for(HiveWriter writer: allWriters.values()) {
            writer.flush(rollToNext);
        }
    }

    /**
     * Closes all writers and remove them from cache
     * @return number of writers retired
     */
    private void closeAllWriters() {
        try {
            //1) Retire writers
            for (Entry<HiveEndPoint,HiveWriter> entry : allWriters.entrySet()) {
                entry.getValue().close();
            }
            //2) Clear cache
            allWriters.clear();
        } catch(Exception e) {
            LOG.warn("unable to close writers. ", e);
        }
    }

    void flushAndCloseWriters() throws Exception {
        try {
            flushAllWriters(false);
        } catch(Exception e) {
            LOG.warn("unable to flush hive writers. ", e);
            throw e;
        } finally {
            closeAllWriters();
        }
    }

    private void enableHeartBeatOnAllWriters() {
        for (HiveWriter writer : allWriters.values()) {
            writer.setHeartBeatNeeded();
        }
    }

    private HiveWriter getOrCreateWriter(HiveEndPoint endPoint)
        throws HiveWriter.ConnectFailure, InterruptedException {
        try {
            HiveWriter writer = allWriters.get( endPoint );
            if( writer == null ) {
                LOG.debug("Creating Writer to Hive end point : " + endPoint);
                writer = HiveUtils.makeHiveWriter(endPoint, callTimeoutPool, ugi, options);
                if(allWriters.size() > options.getMaxOpenConnections()){
                    int retired = retireIdleWriters();
                    if(retired==0) {
                        retireEldestWriter();
                    }
                }
                allWriters.put(endPoint, writer);
            }
            return writer;
        } catch (HiveWriter.ConnectFailure e) {
            LOG.error("Failed to create HiveWriter for endpoint: " + endPoint, e);
            throw e;
        }
    }

    /**
     * Locate writer that has not been used for longest time and retire it
     */
    private void retireEldestWriter() {
        long oldestTimeStamp = System.currentTimeMillis();
        HiveEndPoint eldest = null;
        for (Entry<HiveEndPoint,HiveWriter> entry : allWriters.entrySet()) {
            if(entry.getValue().getLastUsed() < oldestTimeStamp) {
                eldest = entry.getKey();
                oldestTimeStamp = entry.getValue().getLastUsed();
            }
        }
        try {
            LOG.info("Closing least used Writer to Hive end point : " + eldest);
            allWriters.remove(eldest).close();
        } catch (IOException e) {
            LOG.warn("Failed to close writer for end point: " + eldest, e);
        } catch (InterruptedException e) {
            LOG.warn("Interrupted when attempting to close writer for end point: " + eldest, e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * Locate all writers past idle timeout and retire them
     * @return number of writers retired
     */
    private int retireIdleWriters() {
        int count = 0;
        long now = System.currentTimeMillis();
        ArrayList<HiveEndPoint> retirees = new ArrayList<HiveEndPoint>();

        //1) Find retirement candidates
        for (Entry<HiveEndPoint,HiveWriter> entry : allWriters.entrySet()) {
            if(now - entry.getValue().getLastUsed() > options.getIdleTimeout()) {
                ++count;
                retirees.add(entry.getKey());
            }
        }
        //2) Retire them
        for(HiveEndPoint ep : retirees) {
            try {
                LOG.info("Closing idle Writer to Hive end point : {}", ep);
                allWriters.remove(ep).close();
            } catch (IOException e) {
                LOG.warn("Failed to close writer for end point: {}. Error: "+ ep, e);
            } catch (InterruptedException e) {
                LOG.warn("Interrupted when attempting to close writer for end point: " + ep, e);
                Thread.currentThread().interrupt();
            }
        }
        return count;
    }

}
