/*
 * 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.nutch.service.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.WebApplicationException;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.SequenceFile.Reader;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.StringUtils;
import org.apache.nutch.service.NutchReader;

/**
 * Enables reading a sequence file and methods provide different 
 * ways to read the file. 
 * @author Sujen Shah
 *
 */
public class SequenceReader implements NutchReader {

  @Override
  public List<List<String>> read(String path) throws FileNotFoundException {
    // TODO Auto-generated method stub
    List<List<String>> rows= new ArrayList<>();
    Path file = new Path(path);
    SequenceFile.Reader reader;
    try {
      reader = new SequenceFile.Reader(conf, Reader.file(file));
      Writable key = 
          (Writable)ReflectionUtils.newInstance(reader.getKeyClass(), conf);
      Writable value = 
          (Writable)ReflectionUtils.newInstance(reader.getValueClass(), conf);
      
      while(reader.next(key, value)) {
        List<String> row = new ArrayList<>();
        row.add(key.toString());
        row.add(value.toString());
        rows.add(row);
      }
      reader.close();
    }catch(FileNotFoundException fne){ 
      throw new FileNotFoundException();
    }catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      LOG.error("Error occurred while reading file {} : {}", file,
          StringUtils.stringifyException(e));
      throw new WebApplicationException();
    } 
    return rows;
  }

  @Override
  public List<List<String>> head(String path, int nrows) 
      throws FileNotFoundException {
    // TODO Auto-generated method stub
    
    List<List<String>> rows= new ArrayList<>();
    Path file = new Path(path);
    SequenceFile.Reader reader;
    try {
      
      reader = new SequenceFile.Reader(conf, Reader.file(file));
      Writable key = 
          (Writable)ReflectionUtils.newInstance(reader.getKeyClass(), conf);
      Writable value = 
          (Writable)ReflectionUtils.newInstance(reader.getValueClass(), conf);
      int i = 0;
      while(reader.next(key, value) && i<nrows) {
        List<String> row = new ArrayList<>();
        row.add(key.toString());
        row.add(value.toString());
        rows.add(row);
        i++;
      }
      reader.close();
    } catch(FileNotFoundException fne){ 
      throw new FileNotFoundException();
    }catch (IOException e) {
      // TODO Auto-generated catch block
      LOG.error("Error occurred while reading file {} : {}", file,
          StringUtils.stringifyException(e));
      throw new WebApplicationException();
    } 
    return rows;
  }

  @Override
  public List<List<String>> slice(String path, int start, int end) 
      throws FileNotFoundException {
    List<List<String>> rows= new ArrayList<>();
    Path file = new Path(path);
    SequenceFile.Reader reader;
    try {
      
      reader = new SequenceFile.Reader(conf, Reader.file(file));
      Writable key = 
          (Writable)ReflectionUtils.newInstance(reader.getKeyClass(), conf);
      Writable value = 
          (Writable)ReflectionUtils.newInstance(reader.getValueClass(), conf);
      int i = 0;
      
      for(;i<start && reader.next(key, value);i++){} // increment to read start position
      while(reader.next(key, value) && i<end) {
        List<String> row = new ArrayList<>();
        row.add(key.toString());
        row.add(value.toString());
        rows.add(row);
        i++;
      }
      reader.close();
    } catch(FileNotFoundException fne){ 
      throw new FileNotFoundException();
    }catch (IOException e) {
      // TODO Auto-generated catch block
      LOG.error("Error occurred while reading file {} : {}", file,
          StringUtils.stringifyException(e));
      throw new WebApplicationException();
    } 
    return rows;
  }

  @Override
  public int count(String path) throws FileNotFoundException {
    Path file = new Path(path);
    SequenceFile.Reader reader;
    int i = 0;
    try {
      reader = new SequenceFile.Reader(conf, Reader.file(file));
      Writable key = 
          (Writable)ReflectionUtils.newInstance(reader.getKeyClass(), conf);
      Writable value = 
          (Writable)ReflectionUtils.newInstance(reader.getValueClass(), conf);
     
      while(reader.next(key, value)) {
        i++;
      }
      reader.close();
    } catch(FileNotFoundException fne){ 
      throw new FileNotFoundException();
    }catch (IOException e) {
      // TODO Auto-generated catch block
      LOG.error("Error occurred while reading file {} : {}", file,
          StringUtils.stringifyException(e));
      throw new WebApplicationException();
    } 
    return i;
  }

}
