package de.christinecoenen.code.zapp.repositories;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.apache.commons.io.IOUtils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;

import de.christinecoenen.code.zapp.app.livestream.api.model.ChannelInfo;
import de.christinecoenen.code.zapp.app.livestream.repository.ChannelInfoRepository;
import de.christinecoenen.code.zapp.model.ChannelModel;
import de.christinecoenen.code.zapp.model.ISortableChannelList;
import de.christinecoenen.code.zapp.model.json.SortableVisibleJsonChannelList;
import io.reactivex.Single;
import io.reactivex.disposables.Disposable;
import timber.log.Timber;

public class ChannelRepository {

	private final String CHANNEL_INFOS_FILE_NAME = "channelInfoList.json";

	private final Gson gson = new Gson();
	private final Context context;
	private final ISortableChannelList channelList;

	public ChannelRepository(Context context) {
		this.context = context;

		channelList = new SortableVisibleJsonChannelList(context);

		Disposable disposable = getChannelInfoListFromApi()
			.onErrorReturn(t -> getChannelInfoListFromDisk())
			.subscribe(this::onChannelInfoListSuccess, Timber::w);
	}

	public ISortableChannelList getChannelList() {
		channelList.reload();
		return channelList;
	}

	public void deleteCachedChannelInfos() {
		deleteChannelInfoListFromDisk();
		channelList.reload();
	}

	private void onChannelInfoListSuccess(Map<String, ChannelInfo> channelInfoList) {
		try {
			writeChannelInfoListToDisk(channelInfoList);
		} catch (IOException e) {
			Timber.e(e);
		}

		applyToChannelList(channelInfoList);
	}

	private void applyToChannelList(Map<String, ChannelInfo> channelInfoList) {
		for (String channelId : channelInfoList.keySet()) {
			ChannelModel channel = channelList.get(channelId);
			if (channel != null) {
				channel.setStreamUrl(channelInfoList.get(channelId).getStreamUrl());
			}
		}
	}

	private Single<Map<String, ChannelInfo>> getChannelInfoListFromApi() {
		return ChannelInfoRepository.getInstance()
			.getChannelInfoList();
	}

	private Map<String, ChannelInfo> getChannelInfoListFromDisk() throws IOException {
		try (FileInputStream inputStream = context.openFileInput(CHANNEL_INFOS_FILE_NAME)) {
			String json = IOUtils.toString(inputStream, "UTF-8");
			inputStream.close();
			Type type = new TypeToken<Map<String, ChannelInfo>>() {
			}.getType();
			return gson.fromJson(json, type);
		}
	}

	private void writeChannelInfoListToDisk(Map<String, ChannelInfo> channelInfoList) throws IOException {
		try (FileOutputStream fileOutputStream = context.openFileOutput(CHANNEL_INFOS_FILE_NAME, Context.MODE_PRIVATE)) {
			String json = gson.toJson(channelInfoList);
			IOUtils.write(json, fileOutputStream, "UTF-8");
		}
	}

	private void deleteChannelInfoListFromDisk() {
		context.deleteFile(CHANNEL_INFOS_FILE_NAME);
	}
}

@@ -1019,16 +1019,67 @@
 nelList;
+%0A%09private Map%3CString, ChannelInfo%3E channelInfoList;
 %0A%0A%09publi
@@ -1447,16 +1447,55 @@
 load();%0A
+%09%09applyToChannelList(channelInfoList);%0A
 %09%09return
@@ -1805,16 +1805,58 @@
 );%0A%09%09%7D%0A%0A
+%09%09this.channelInfoList = channelInfoList;%0A
 %09%09applyT

Fix bug where stream urls are not loaded correctly from server