package device.cdPlayer;

import device.Device;
import device.cdPlayer.exceptions.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CDPlayer implements Device {

    // 0-Leer; true-1
    private int CdDriveContent=0;
    private int CdFlap=0;
    private int volume = 0;
    private String infoText=null;
    private List<String> supportedFormats = new ArrayList<String>(Arrays.asList(new String[] {"Audio","MP3","WMA","AAC"}));

    private String actualPlayTrack="";
    private CD loadedCD=null;

    private CDWechseler cdWechseler=null;
    private String activeSource="CDDrive";//or CDWechseler

    private List<String>favoriteSongs=new ArrayList<>();

    @Override
    public void louder() {
        if(volume < 100) {
            volume += 1;
        } else {
            volume = 100;
        }
    }

    @Override
    public void quieter() {
        if(volume > 0) {
            volume -= 1;
        } else {
            volume = 0;
        }
    }

    @Override
    public int getVolume() {
        return volume;
    }

    @Override
    public void next() {
        List<String> playList =  Arrays.asList(loadedCD.getPlayList());
        int indexOfActualPlayTrack=playList.indexOf(actualPlayTrack);
        int indexOfNextPlayTrack=(indexOfActualPlayTrack+1)%loadedCD.getPlayList().length;
        this.actualPlayTrack=playList.get(indexOfNextPlayTrack );
    }

    @Override
    public void prev() {
        List<String> playList =  Arrays.asList(loadedCD.getPlayList());
        int actualIndex=playList.indexOf(actualPlayTrack);
        if(actualIndex>0){
            actualIndex-=1;
        }else{
            actualIndex=0;
        }
        this.actualPlayTrack=playList.get(actualIndex);
    }

    @Override
    public String getInfoText() {
        if(infoText==null){
            throw new ReturnValueNullException();
        }
        return infoText;
    }

    @Override
    public String[] getOptions() {
        Method[] methods=this.getClass().getDeclaredMethods();
        String[] outMethods=new String[methods.length];

        for (int i = 0; i <methods.length ; i++) {
            outMethods[i]=methods[i].getName();
        }
        return outMethods;
    }

    @Override
    public String chooseItem(int itemNr) {
        if(this.loadedCD==null){
            throw new ReturnValueNullException();
        }
        if(itemNr<0){
            throw new NegativeInputException();
        }
        if(!(itemNr>=0  && itemNr<loadedCD.getPlayList().length)){
            throw new ItemNumberNotFoundException();
        }

        return loadedCD.getPlayList()[itemNr];
    }

    @Override
    public String[] getItemList() {
        return loadedCD.getPlayList();
    }

    @Override
    public String mute() {
        return null;
    }

    @Override
    public String unmute() {
        return null;
    }

    @Override
    public String play() {
        if(isCdFlapOpen()){
            throw new CdFlapIsOpenException();
        }
        else if(!isCdFlapOpen()&&getCdDriveContent()==0){
            throw new NoCDException();
        }
        else if(!isCdFlapOpen()&&getCdDriveContent()==1&&!checkFormat(loadedCD.getFormat())){
            throw new FormatNotSupportedException();
        }
        else if(!isCdFlapOpen()&&getCdDriveContent()==1&&checkFormat(loadedCD.getFormat())){
            System.out.println(loadedCD.getFormat()+" "+this.actualPlayTrack+" is playing.");
            return "AllConditionsForPlayMet";
        }
        return null;
    }
    public String changePlaySource(){
        if(activeSource.equals("CDDrive")) {
            this.activeSource = "CDWechseler";
            this.cdWechseler=new CDWechseler();
            this.cdWechseler.activate();
        }else this.activeSource="CDDrive";

        return activeSource;
    }
    public void loadCDWechseler(CD cd,int index){
        if(cdWechseler==null||!cdWechseler.isRunning()){
            throw new CDWechselerNotRunningException();
        }
        if(!(this.supportedFormats.contains(cd.getFormat()))){
            throw new FormatNotSupportedException();
        }
        if(index>10){
            throw new MaxCapacityExceededException();
        }
        cdWechseler.loadOneCD(cd,index);
        this.loadedCD=cdWechseler.getCDList().get(0);
    }
    public void changeToNextCD(){
        if(activeSource.equals("CDDrive")){
            throw new ChangeCDOnlyOnCDWechselerException();
        }

        List<CD> CDList = cdWechseler.getCDList();
        int indexOfLoadedCD=CDList.indexOf(loadedCD);
        int nextIndex=(indexOfLoadedCD+1)%CDList.size();
        this.loadedCD=CDList.get(nextIndex);
    }
    public void addToFavoriteSongs(String song){
        if(activeSource.equals("CDDrive")){
            throw new CDWechselerNotRunningException();
        }
        if(!(favoriteSongs.contains(song))) {
            favoriteSongs.add(song);
        }
    }

    //Getters, Setters und SupportMethods
    public void setCD(CD _loadedCD) {
        loadedCD=_loadedCD;
        this.setCdDriveContent();
        this.actualPlayTrack=loadedCD.getPlayList()[0];
    }

    private void setCdDriveContent() {
        CdDriveContent = 1;
    }

    public void tapOnCdFlap(){
        this.CdFlap+=1;
    }
    private boolean checkFormat(String format){
        if(this.supportedFormats.contains(format))
            return true;
        else return false;
    }
    private int getCdDriveContent() {
        return CdDriveContent;
    }
    private boolean isCdFlapOpen() {
        if(CdFlap==1) {
            return true;
        }
        else
            return false;
    }

    public String getSongByNumber(int songNr){
        List<String> playList =  Arrays.asList(loadedCD.getPlayList());
        return playList.get(songNr);
    }

    public String getActualPlayTrack() {
        return actualPlayTrack;
    }

    public void setInfoText() {
        this.infoText=this.getClass().getSimpleName()+": Item->"+actualPlayTrack+" from Album->"+this.loadedCD.getAlbumName()+" running.";
    }

    public CD getCD() {
        return this.loadedCD;
    }

    public CDWechseler getCdWechseler() {
        return cdWechseler;
    }

    public List<String> getFavoriteSongs() {
        return favoriteSongs;
    }
}