brake this into smaller methods, because this is very hard to read