Working solution. Still need some tests and improvments