package allen.town.podcast.parser.media.vorbis;

import android.util.Log;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import allen.town.podcast.model.feed.Chapter;
import allen.town.podcast.parser.media.BuildConfig;

public class VorbisCommentChapterReader extends VorbisCommentReader {
    private static final String TAG = "VorbisCommentChptrReadr";

    private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*";
    private static final String CHAPTER_ATTRIBUTE_TITLE = "name";
    private static final String CHAPTER_ATTRIBUTE_LINK = "url";
    private static final int CHAPTERXXX_LENGTH = "chapterxxx".length();

    private final List<Chapter> chapters = new ArrayList<>();

    public VorbisCommentChapterReader(InputStream input) {
        super(input);
    }

    @Override
    public boolean handles(String key) {
        return key.matches(CHAPTER_KEY);
    }

    @Override
    public void onContentVectorValue(String key, String value) throws VorbisCommentReaderException {
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "Key: " + key + ", value: " + value);
        }
        String attribute = getAttributeTypeFromKey(key);
        int id = getIdFromKey(key);
        Chapter chapter = getChapterById(id);
        if (attribute == null) {
            if (getChapterById(id) == null) {
                // new chapter
                long start = getStartTimeFromValue(value);
                chapter = new Chapter();
                chapter.setChapterId("" + id);
                chapter.setStart(start);
                chapters.add(chapter);
            } else {
                throw new VorbisCommentReaderException("Found chapter with duplicate ID (" + key + ", " + value + ")");
            }
        } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) {
            if (chapter != null) {
                chapter.setTitle(value);
            }
        } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) {
            if (chapter != null) {
                chapter.setLink(value);
            }
        }
    }

    private Chapter getChapterById(long id) {
        for (Chapter c : chapters) {
            if (("" + id).equals(c.getChapterId())) {
                return c;
            }
        }
        return null;
    }

    public static long getStartTimeFromValue(String value)
            throws VorbisCommentReaderException {
        String[] parts = value.split(":");
        if (parts.length >= 3) {
            try {
                long hours = TimeUnit.MILLISECONDS.convert(
                        Long.parseLong(parts[0]), TimeUnit.HOURS);
                long minutes = TimeUnit.MILLISECONDS.convert(
                        Long.parseLong(parts[1]), TimeUnit.MINUTES);
                if (parts[2].contains("-->")) {
                    parts[2] = parts[2].substring(0, parts[2].indexOf("-->"));
                }
                long seconds = TimeUnit.MILLISECONDS.convert(
                        ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS);
                return hours + minutes + seconds;
            } catch (NumberFormatException e) {
                throw new VorbisCommentReaderException(e);
            }
        } else {
            throw new VorbisCommentReaderException("Invalid time string");
        }
    }

    /**
     * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx*
     *
     * @return the id of the chapter key or -1 if the id couldn't be read.
     * @throws VorbisCommentReaderException
     * */
    private static int getIdFromKey(String key) throws VorbisCommentReaderException {
        if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx
            try {
                String strId = key.substring(8, 10);
                return Integer.parseInt(strId);
            } catch (NumberFormatException e) {
                throw new VorbisCommentReaderException(e);
            }
        }
        throw new VorbisCommentReaderException("key is too short (" + key + ")");
    }

    /**
     * Get the string that comes after 'CHAPTERxxx', for example 'name' or
     * 'url'.
     */
    private static String getAttributeTypeFromKey(String key) {
        if (key.length() > CHAPTERXXX_LENGTH) {
            return key.substring(CHAPTERXXX_LENGTH);
        }
        return null;
    }

    public List<Chapter> getChapters() {
        return chapters;
    }

}
