/*
 * Copyright (C) 2011 The Guava Authors
 *
 * 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.
 */

package com.google.common.hash;

import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;

import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;

import javax.annotation.Nullable;

/**
 * Funnels for common types. All implementations are serializable.
 *
 * @author Dimitris Andreou
 * @since 11.0
 */
@Beta
public final class Funnels {
  private Funnels() {}

  /**
   * Returns a funnel that extracts the bytes from a {@code byte} array.
   */
  public static Funnel<byte[]> byteArrayFunnel() {
    return ByteArrayFunnel.INSTANCE;
  }

  private enum ByteArrayFunnel implements Funnel<byte[]> {
    INSTANCE;

    public void funnel(byte[] from, PrimitiveSink into) {
      into.putBytes(from);
    }

    @Override public String toString() {
      return "Funnels.byteArrayFunnel()";
    }
  }

  /**
   * Returns a funnel that extracts the characters from a {@code CharSequence}, a character at a
   * time, without performing any encoding. If you need to use a specific encoding, use
   * {@link Funnels#stringFunnel(Charset)} instead.
   *
   * @since 15.0 (since 11.0 as {@code Funnels.stringFunnel()}.
   */
  public static Funnel<CharSequence> unencodedCharsFunnel() {
    return UnencodedCharsFunnel.INSTANCE;
  }

  private enum UnencodedCharsFunnel implements Funnel<CharSequence> {
    INSTANCE;

    public void funnel(CharSequence from, PrimitiveSink into) {
      into.putUnencodedChars(from);
    }

    @Override public String toString() {
      return "Funnels.unencodedCharsFunnel()";
    }
  }

  /**
   * Returns a funnel that encodes the characters of a {@code CharSequence} with the specified
   * {@code Charset}.
   *
   * @since 15.0
   */
  public static Funnel<CharSequence> stringFunnel(Charset charset) {
    return new StringCharsetFunnel(charset);
  }

  private static class StringCharsetFunnel implements Funnel<CharSequence>, Serializable {
    private final Charset charset;

    StringCharsetFunnel(Charset charset) {
      this.charset = Preconditions.checkNotNull(charset);
    }

    public void funnel(CharSequence from, PrimitiveSink into) {
      into.putString(from, charset);
    }

    @Override public String toString() {
      return "Funnels.stringFunnel(" + charset.name() + ")";
    }

    @Override public boolean equals(@Nullable Object o) {
      if (o instanceof StringCharsetFunnel) {
        StringCharsetFunnel funnel = (StringCharsetFunnel) o;
        return this.charset.equals(funnel.charset);
      }
      return false;
    }

    @Override public int hashCode() {
      return StringCharsetFunnel.class.hashCode() ^ charset.hashCode();
    }

    Object writeReplace() {
      return new SerializedForm(charset);
    }

    private static class SerializedForm implements Serializable {
      private final String charsetCanonicalName;

      SerializedForm(Charset charset) {
        this.charsetCanonicalName = charset.name();
      }

      private Object readResolve() {
        return stringFunnel(Charset.forName(charsetCanonicalName));
      }
    
      private static final long serialVersionUID = 0;
    }
  }

  /**
   * Returns a funnel for integers.
   *
   * @since 13.0
   */
  public static Funnel<Integer> integerFunnel() {
    return IntegerFunnel.INSTANCE;
  }

  private enum IntegerFunnel implements Funnel<Integer> {
    INSTANCE;

    public void funnel(Integer from, PrimitiveSink into) {
      into.putInt(from);
    }

    @Override public String toString() {
      return "Funnels.integerFunnel()";
    }
  }

  /**
   * Returns a funnel that processes an {@code Iterable} by funneling its elements in iteration
   * order with the specified funnel.  No separators are added between the elements.
   *
   * @since 15.0
   */
  public static <E> Funnel<Iterable<? extends E>> sequentialFunnel(Funnel<E> elementFunnel) {
    return new SequentialFunnel<E>(elementFunnel);
  }

  private static class SequentialFunnel<E> implements Funnel<Iterable<? extends E>>, Serializable {
    private final Funnel<E> elementFunnel;

    SequentialFunnel(Funnel<E> elementFunnel) {
      this.elementFunnel = Preconditions.checkNotNull(elementFunnel);
    }

    public void funnel(Iterable<? extends E> from, PrimitiveSink into) {
      for (E e : from) {
        elementFunnel.funnel(e, into);
      }
    }

    @Override public String toString() {
      return "Funnels.sequentialFunnel(" + elementFunnel + ")";
    }

    @Override public boolean equals(@Nullable Object o) {
      if (o instanceof SequentialFunnel) {
        SequentialFunnel<?> funnel = (SequentialFunnel<?>) o;
        return elementFunnel.equals(funnel.elementFunnel);
      }
      return false;
    }

    @Override public int hashCode() {
      return SequentialFunnel.class.hashCode() ^ elementFunnel.hashCode();
    }
  }

  /**
   * Returns a funnel for longs.
   * 
   * @since 13.0
   */
  public static Funnel<Long> longFunnel() {
    return LongFunnel.INSTANCE;
  }
  
  private enum LongFunnel implements Funnel<Long> {
    INSTANCE;
    
    public void funnel(Long from, PrimitiveSink into) {
      into.putLong(from);
    }
    
    @Override public String toString() {
      return "Funnels.longFunnel()";
    }
  }
  
  /**
   * Wraps a {@code PrimitiveSink} as an {@link OutputStream}, so it is easy to
   * {@link Funnel#funnel funnel} an object to a {@code PrimitiveSink}
   * if there is already a way to write the contents of the object to an {@code OutputStream}.  
   * 
   * <p>The {@code close} and {@code flush} methods of the returned {@code OutputStream}
   * do nothing, and no method throws {@code IOException}.
   * 
   * @since 13.0
   */
  public static OutputStream asOutputStream(PrimitiveSink sink) {
    return new SinkAsStream(sink);
  }
  
  private static class SinkAsStream extends OutputStream {
    final PrimitiveSink sink;
    SinkAsStream(PrimitiveSink sink) {
      this.sink = Preconditions.checkNotNull(sink);
    }
    
    @Override public void write(int b) {
      sink.putByte((byte) b);
    }

    @Override public void write(byte[] bytes) {
      sink.putBytes(bytes);
    }

    @Override public void write(byte[] bytes, int off, int len) {
      sink.putBytes(bytes, off, len);
    }
    
    @Override public String toString() {
      return "Funnels.asOutputStream(" + sink + ")";
    }
  }
}
