/*
 * Copyright 2014 Objectos, Fábrica de Software LTDA.
 *
 * 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 br.com.objectos.way.io;

import static br.com.objectos.testing.MoreMatchers.equalTo;
import static com.google.common.collect.Lists.transform;
import static org.hamcrest.MatcherAssert.assertThat;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

import br.com.objectos.comuns.io.Line;
import br.com.objectos.comuns.io.xls.AbstractXlsConverter;
import br.com.objectos.comuns.io.xls.CellWrapper;
import br.com.objectos.comuns.io.xls.FakeBooleanXlsConverterBuilder;
import br.com.objectos.way.io.Table.Error;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

/**
 * @author edenir.anschau@objectos.com.br (Edenir Norberto Anschau)
 */
@Test
public class TableReaderConverterTest {

  private TableReader<Entity> reader;

  @BeforeClass
  public void setupReader() {
    reader = WayIO.tableReaderOf(Entity.class)
        .xls()
        .skipFirstLines(1)
        .parseWith(new ThisParser())
        .filterWith(new EntityFilter())
        .build();
  }

  public void read_with_converter() {
    List<Entity> fakes = FakeEntities.getAll();
    List<String> expected = transform(fakes, EntityToString.INSTANCE);

    Table<Entity> table = reader
        .readResource("/xls/reader.xls")
        .sheetNamed("normal");
    printErrors(table);

    List<Entity> rows = table.getRows();
    List<String> res = transform(rows, EntityToString.INSTANCE);

    assertThat(res.size(), equalTo(3));
    assertThat(res, equalTo(expected));
  }

  public void read_with_converter_xlsx() {
    List<Entity> fakes = FakeEntities.getAll();
    List<String> expected = transform(fakes, EntityToString.INSTANCE);

    Table<Entity> table = reader
        .readResource("/xls/reader.xlsx")
        .sheetNamed("normal");
    printErrors(table);

    List<Entity> rows = table.getRows();
    List<String> res = transform(rows, EntityToString.INSTANCE);

    assertThat(res.size(), equalTo(3));
    assertThat(res, equalTo(expected));
  }

  private void printErrors(Table<Entity> table) {
    List<Error> errors = table.getErrors();
    for (Error error : errors) {
      System.out.println(error);
    }
  }

  private class ThisParser extends EntityParser {

    @Override
    protected void configure() {
      AbstractXlsConverter<Boolean> booleanXlsConverter = FakeBooleanXlsConverterBuilder.builder()
          .trueValue("X")
          .falseValue("")
          .build();

      convert(Boolean.class).with(booleanXlsConverter);
      convert(LocalDate.class).with(new LocalDateXlsConverter());
    }

    @Override
    boolean parseBoolean(Line line) {
      return line.column(4).or(Boolean.class, Boolean.FALSE);
    }

  }

  private class LocalDateXlsConverter extends AbstractXlsConverter<LocalDate> {
    @Override
    protected LocalDate convert(CellWrapper cell) {
      Date date = cell.getDate();
      return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    @Override
    protected Class<? extends LocalDate> getRawType() {
      return LocalDate.class;
    }
  }

}