import numpy as np
import logging
from tqdm import tqdm
class Perceptron:
    def __init__(self,eta,epochs):
        self.weights=np.random.randn(3)*1e-4
        logging.info(f"Inital Weights before training:{self.weights}")
        self.eta=eta
        self.epochs=epochs
        
    def activation(self,inputs,weights):
        z=np.dot(inputs,weights)
        return np.where(z>0,1,0)
    
    def fit(self,X,y):
        self.X=X
        self.y=y
        X_with_bias=np.c_[self.X,-np.ones((len(self.X),1))]
        logging.info(f"X_with_bias:{X_with_bias}")
        for epoch in tqdm(range(self.epochs),total=self.epochs,desc="Training the model"):
            logging.info(f"Epochs:{epoch}")
            y_hat=self.activation(X_with_bias,self.weights)
            logging.info(f"Predicted Value after forward pass:\n{y_hat}")
            self.error=self.y-y_hat
            logging.info(f"Error:\n{self.error}")
            self.weights=self.weights+self.eta*np.dot(X_with_bias.T,self.error)
            logging.info(f"Updated weights after epoch :\n{epoch}/{self.epochs}:\n{self.weights}")
            
    def predict(self,X):
        X_with_bias=np.c_[X,-np.ones((len(X),1))]
        return self.activation(X_with_bias,self.weights)
    
    def total_loss(self):
        total_loss=np.sum(self.error)
        logging.info(f"Total Loss:{total_loss}")
        return total_loss