package org.apache.samoa.utils;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2014 - 2015 Apache Software Foundation
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.ByteArrayOutputStream;

import org.apache.samza.config.Config;
import org.apache.samza.serializers.Serde;
import org.apache.samza.serializers.SerdeFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

/**
 * Implementation of Samza's SerdeFactory that uses Kryo to serialize/deserialize objects
 * 
 * @author Anh Thu Vu
 * @param <T>
 * 
 */
public class SamzaKryoSerdeFactory<T> implements SerdeFactory<T> {

  private static final Logger logger = LoggerFactory.getLogger(SamzaKryoSerdeFactory.class);

  public static class SamzaKryoSerde<V> implements Serde<V> {
    private Kryo kryo;

    public SamzaKryoSerde(String registrationInfo) {
      this.kryo = new Kryo();
      this.register(registrationInfo);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void register(String registrationInfo) {
      if (registrationInfo == null)
        return;

      String[] infoList = registrationInfo.split(SamzaConfigFactory.COMMA);

      Class targetClass = null;
      Class serializerClass = null;
      Serializer serializer = null;

      for (String info : infoList) {
        String[] fields = info.split(SamzaConfigFactory.COLON);

        targetClass = null;
        serializerClass = null;
        if (fields.length > 0) {
          try {
            targetClass = Class.forName(fields[0].replace(SamzaConfigFactory.QUESTION_MARK,
                SamzaConfigFactory.DOLLAR_SIGN));
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        if (fields.length > 1) {
          try {
            serializerClass = Class.forName(fields[1].replace(SamzaConfigFactory.QUESTION_MARK,
                SamzaConfigFactory.DOLLAR_SIGN));
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }

        if (targetClass != null) {
          if (serializerClass == null) {
            kryo.register(targetClass);
          }
          else {
            serializer = resolveSerializerInstance(kryo, targetClass, (Class<? extends Serializer>) serializerClass);
            kryo.register(targetClass, serializer);
          }
        }
        else {
          logger.info("Invalid registration info:{}", info);
        }
      }
    }

    @SuppressWarnings("rawtypes")
    private static Serializer resolveSerializerInstance(Kryo k, Class superClass,
        Class<? extends Serializer> serializerClass) {
      try {
        try {
          return serializerClass.getConstructor(Kryo.class, Class.class).newInstance(k, superClass);
        } catch (Exception ex1) {
          try {
            return serializerClass.getConstructor(Kryo.class).newInstance(k);
          } catch (Exception ex2) {
            try {
              return serializerClass.getConstructor(Class.class).newInstance(superClass);
            } catch (Exception ex3) {
              return serializerClass.newInstance();
            }
          }
        }
      } catch (Exception ex) {
        throw new IllegalArgumentException("Unable to create serializer \""
            + serializerClass.getName()
            + "\" for class: "
            + superClass.getName(), ex);
      }
    }

    /*
     * Implement Samza Serde interface
     */
    @Override
    public byte[] toBytes(V obj) {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      Output output = new Output(bos);
      kryo.writeClassAndObject(output, obj);
      output.flush();
      output.close();
      return bos.toByteArray();
    }

    @SuppressWarnings("unchecked")
    @Override
    public V fromBytes(byte[] byteArr) {
      Input input = new Input(byteArr);
      Object obj = kryo.readClassAndObject(input);
      input.close();
      return (V) obj;
    }

  }

  @Override
  public Serde<T> getSerde(String name, Config config) {
    return new SamzaKryoSerde<T>(config.get(SamzaConfigFactory.SERDE_REGISTRATION_KEY));
  }
}
