func (env *Env) SpotifyGetKeys(w http.ResponseWriter, r *http.Request) {
	authClient = setup()
	token, err := pullToken(r, env)
	if err != nil {
		common.DisplayAppError(w, err, "error with pulling token, may need to re-auth", 500)
		return
	}

	//have our SpotifyClient here:
	client := authClient.FinalAuth(token)

	var keys IncomingKeys

	if r.Method == "POST" {
		err := json.NewDecoder(r.Body).Decode(&keys)
		if err != nil {
			common.DisplayAppError(w, err, "Invalid Keys data", 500)
			return
		}
	}

	notesChosen := keys.Data.Keys

	songs, _ := GetSongsByKey(notesChosen, client)

	reqcontext.Clear(r)
	if j, err := json.Marshal(SongKeysResource{Data: songs}); err != nil {
		fmt.Println("error in controllers.SpotifyGetKeys json.Marshal")
		return
	} else {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
	}
}
func (env *Env) RegisterUser(w http.ResponseWriter, r *http.Request) {

	var usr UserResource
	var token string
	if r.Method == "POST" {
		err := json.NewDecoder(r.Body).Decode(&usr)
		if err != nil {
			common.DisplayAppError(w, err, "Invalid User data", 500)
			return
		}
	}

	user := &usr.Data

	err := RegisterUserDB(user, env)
	//DB error
	if err != nil {
		//maybe make an error stuct to tell whether it was the username or email duplicate.
		common.DisplayAppError(w, err, "User could not be registered.", 500)
		return
	}

	cookie, err := common.GenerateCookieToken(user.Username, "app", user.User_ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error while generating the access token for cookie", 500)
		return
	}

	//generate token for response:
	token, err = common.GenerateToken(user.Username, "app", user.User_ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error while generating the access token for sessions", 500)
		return
	}

	//set the responseUser data:
	responseUser := RegisterAuthUserModel{User: user, Token: token}

	if j, err := json.Marshal(RegisterAuthUserResource{Data: responseUser}); err != nil {
		fmt.Println("error in controllers.RegisterUser json.Marshal")
		return
	} else {
		http.SetCookie(w, &cookie)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
	}
}
//handler for /authLogin
func SpotifyAuthorization(w http.ResponseWriter, r *http.Request) {

	//setup the cookie:
	session, err := store.Get(r, "spotify_auth_state")
	if err != nil {
		common.DisplayAppError(w, err, "Error getting session in SpotifyAuthorization", 500)
		return
	}
	session.Options = &sessions.Options{
		MaxAge: 60 * 2,
	}

	//gets an AuthUser struct.
	authClient = setup()
	//uses AuthUser struct to get an auth url:
	url, state := GetURL(authClient)

	session.Values["state_key"] = state
	session.Save(r, w)

	if j, err := json.Marshal(AuthURI{Uri: url}); err != nil {
		fmt.Println("error in controllers.SpotifyAuthorization json.Marshal")
		return
	} else {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
	}
}
func LogOut(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie("Auth")
	if err != nil {
		err := errors.New("Error logging out (Auth)")
		common.DisplayAppError(w, err, "Error logging out", 500)
	}
	if err == nil {
		cookie.Expires, _ = time.Parse("2006-01-02 15:04:05.0000000 -0700 MST", "2006-01-02 15:04:05.0000000 -0700 MST")
		cookie.MaxAge = -1
		http.SetCookie(w, cookie)
	}

	spotifyCookie, err := r.Cookie("Spotify_Auth")
	if err != nil {
		err := errors.New("Error logging out (Spotify_Auth)")
		common.DisplayAppError(w, err, "Error logging out", 500)
	}
	if err == nil {
		spotifyCookie.MaxAge = -1
		http.SetCookie(w, spotifyCookie)
	}

	w.Header().Set("Content-Type", "application/json")
}
func (env *Env) LoginUser(w http.ResponseWriter, r *http.Request) {

	var usr LoginResource
	var token string

	if r.Method == "POST" {
		err := json.NewDecoder(r.Body).Decode(&usr)
		if err != nil {
			common.DisplayAppError(w, err, "Invalid Login data", 500)
			return
		}
	}

	user := &usr.Data
	loginUser := models.User{
		Email:    user.Email,
		Password: user.Password,
	}

	//login logic robust enough to be done inline:
	query := "SELECT passwords.password,users.user_id FROM passwords INNER JOIN users ON passwords.user_id = users.user_id WHERE users.email=?"
	stmt, err := env.Db.PrepareQuery(query)
	if err != nil {
		common.DisplayAppError(w, err, "Error in database query", 500)
		return
	}
	defer stmt.Close()

	repo := &data.UserRepository{S: stmt}
	userInfo, err := repo.Login(loginUser)
	if err != nil {
		common.DisplayAppError(w, err, "Invalid login credentials", 401)
		return
	}

	//getting jwt for cookie:
	cookie, err := common.GenerateCookieToken(userInfo.Username, "app", userInfo.User_ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error while generating the access token for cookie", 500)
		return
	}

	//generate token for response:
	token, err = common.GenerateToken(userInfo.Username, "app", userInfo.User_ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error while generating the access token for sessions", 500)
		return
	}
	//set the responseUser data:
	responseUser := AuthUserModel{User: userInfo, Token: token}

	if j, err := json.Marshal(AuthUserResource{Data: responseUser}); err != nil {
		common.DisplayAppError(w, err, "An unexpected error has occurred", 500)
		return
	} else {
		http.SetCookie(w, &cookie)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(j)
	}
}
func (env *Env) Scores(w http.ResponseWriter, r *http.Request) {
	var query string

	vars := mux.Vars(r)
	game_mode := vars["mode"]

	var score ScoreResource

	if r.Method == "POST" {
		err := json.NewDecoder(r.Body).Decode(&score)
		if err != nil {
			common.DisplayAppError(w, err, "Invalid Score data", 500)
			return
		}
	}

	scoreData := score.Data

	//getting the username and id from gorilla/context request context:

	query = "SELECT round_id FROM rounds WHERE mode_name=?"
	id, err := env.Db.Search(query, game_mode)
	round_id := id.(int64)
	if err != nil {
		common.DisplayAppError(w, err, "Unexpected error in Scores DB", 500)
		return
	}
	scoreData.Round_ID = round_id

	if loginType, ok := reqcontext.GetOk(r, "LoginType"); ok {
		scoreData.Login_Type = loginType.(string)
	}
	if scoreData.Login_Type == "app" {
		if id, ok := reqcontext.GetOk(r, "ID"); ok {
			query = "INSERT INTO scores(round_id,score,user_id) VALUES(?,?,?)"
			scoreData.User_ID = id.(int64)
		}
	} else {
		if id, ok := reqcontext.GetOk(r, "UserID"); ok {
			query = "INSERT INTO spotify_scores(round_id,score,spotify_id) VALUES(?,?,?)"
			scoreData.Spotify_ID = id.(string)
		}
	}

	fmt.Println(scoreData.Spotify_ID)
	//scoreData.Date_Complete = timeStamp
	stmt, err := env.Db.PrepareQuery(query)
	defer stmt.Close()
	if err != nil {
		common.DisplayAppError(w, err, "Unexpected error in Scores DB", 500)
		return
	}
	repo := &data.ScoresRepository{S: stmt}
	_, err = repo.InsertScore(&scoreData)

	if err != nil {
		common.DisplayAppError(w, err, "Unexpected error in Scores DB", 500)
		return
	}
	reqcontext.Clear(r)
	w.WriteHeader(http.StatusNoContent)
}
//handler for /callback
func (env *Env) SpotifyCallback(w http.ResponseWriter, r *http.Request) {
	//check cookie:
	session, err := store.Get(r, "spotify_auth_state")
	if err != nil {
		common.DisplayAppError(w, err, "Error getting session in SpotifyCallback", 500)
		return
	}
	checkState := session.Values["state_key"]

	// get state query parameter and check it it matches cookie:
	state := r.FormValue("state")
	if checkState == "" || checkState != state || state == "" {
		common.DisplayAppError(w, err, "Not valid Oauth state in SpotifyCallback. Browser identification issue.", 500)
		return
	}

	//will return a token
	token, err := authClient.Token(state, r)
	if err != nil {
		common.DisplayAppError(w, err, "Error getting token", http.StatusForbidden)
		return
	}

	client := authClient.FinalAuth(token)
	//clear state:
	session.Values["state_key"] = ""
	session.Options = &sessions.Options{
		MaxAge: -1,
	}
	session.Save(r, w)

	encryptToken := common.EncryptToken{
		Key:   RandomString(16),
		Token: client.Token,
	}

	user, err := client.GetCurrentProfile()
	if err != nil {
		common.DisplayAppError(w, err, "Error after User auth", 500)
		return
	}
	//check and register if new:
	err = spotifyUserStorage(user, env)
	if err != nil {
		common.DisplayAppError(w, err, "Error in spotifyUserStorage", 500)
		return
	}
	//store token in DB
	err = spotifyTokenStorage(encryptToken, user, env)
	if err != nil {
		common.DisplayAppError(w, err, "Error in spotifyTokenStorage", 500)
		return
	}

	//write cookie:
	cookie, err := encryptToken.GenerateSpotifyCookieToken(user.ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error Generating spotify jwt token", 500)
		return
	}

	sessionToken, err := encryptToken.GenerateSpotifySessionToken(user.ID)
	if err != nil {
		common.DisplayAppError(w, err, "Error Generating spotify jwt token", 500)
		return
	}

	http.SetCookie(w, &cookie)
	queryURL := queryMaker(user, sessionToken)
	http.Redirect(w, r, queryURL, 302)
	//also clear the cookie.
}