// run receives pubsub messages from Redis after establishing a connection.
// When a valid message is received it is broadcast to all connected websockets
func (rr *redisReceiver) run() {
	conn := rr.pool.Get()
	defer conn.Close()
	psc := redis.PubSubConn{conn}
	psc.Subscribe(CHANNEL)
	for {
		switch v := psc.Receive().(type) {
		case redis.Message:
			log.WithFields(log.Fields{
				"channel": v.Channel,
				"message": string(v.Data),
			}).Println("Redis Message Received")
			msg, err := validateMessage(v.Data)
			if err != nil {
				log.WithFields(log.Fields{
					"err":  err,
					"data": v.Data,
					"msg":  msg,
				}).Error("Error unmarshalling message from Redis")
				continue
			}
			rr.broadcast(v.Data)
		case redis.Subscription:
			log.WithFields(log.Fields{
				"channel": v.Channel,
				"kind":    v.Kind,
				"count":   v.Count,
			}).Println("Redis Subscription Received")
		case error:
			log.WithField("err", v).Errorf("Error while subscribed to Redis channel %s", CHANNEL)
		default:
			log.WithField("v", v).Println("Unknown Redis receive during subscription")
		}
	}
}
func main() {
	redisURL := os.Getenv("REDIS_URL")
	redisPool, err := newRedisPool(redisURL)
	if err != nil {
		log.WithField("url", redisURL).Fatal("Unable to create Redis pool")
	}

	rr = newRedisReceiver(redisPool)
	go rr.run()
	rw = newRedisWriter(redisPool)
	go rw.run()

	port := os.Getenv("PORT")
	if port == "" {
		log.WithField("PORT", port).Fatal("$PORT must be set")
	}

	mux := http.NewServeMux()
	mux.HandleFunc("/ws", handleWebsocket)

	n := negroni.Classic()
	n.UseHandler(mux)
	n.Run(":" + port)
}
// handleWebsocket connection. Update to
func handleWebsocket(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}

	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.WithField("err", err).Println("Upgrading to websockets")
		http.Error(w, "Error Upgrading to websockets", 400)
		return
	}

	id := rr.register(ws)

	for {
		mt, data, err := ws.ReadMessage()
		ctx := log.Fields{"mt": mt, "data": data, "err": err}
		if err != nil {
			if err == io.EOF {
				log.WithFields(ctx).Info("Websocket closed!")
			} else {
				log.WithFields(ctx).Error("Error reading websocket message")
			}
			break
		}
		switch mt {
		case websocket.TextMessage:
			msg, err := validateMessage(data)
			if err != nil {
				ctx["msg"] = msg
				ctx["err"] = err
				log.WithFields(ctx).Error("Invalid Message")
				break
			}
			rw.publish(data)
		default:
			log.WithFields(ctx).Warning("Unknown Message!")
		}
	}

	rr.deRegister(id)

	ws.WriteMessage(websocket.CloseMessage, []byte{})
}